app/scripts/lib/mapbox-gl.js

Maintainability

<<<<<<< Updated upstream

60.39

Lines of code

21901

=======

60.36

Lines of code

43051

>>>>>>> Stashed changes

Difficulty

<<<<<<< Updated upstream

418.06

Estimated Errors

364.47

=======

834.11

Estimated Errors

724.42

>>>>>>> Stashed changes

Function weight

By Complexity

By SLOC

======= var lastPositionedGlyph = positionedGlyphs[positionedGlyphs.length - 1]; var lastLineLength = lastPositionedGlyph.x + glyphs[lastPositionedGlyph.codePoint].advance; maxLineLength = Math.max(maxLineLength, lastLineLength); var height = (line + 1) * lineHeight; justifyLine(positionedGlyphs, glyphs, lineStartIndex, positionedGlyphs.length - 1, justify); align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line); // Calculate the bounding box shaping.top += -verticalAlign * height; shaping.bottom = shaping.top + height; shaping.left += -horizontalAlign * maxLineLength; shaping.right = shaping.left + maxLineLength; } function justifyLine(positionedGlyphs, glyphs, start, end, justify) { var lastAdvance = glyphs[positionedGlyphs[end].codePoint].advance; var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify; for (var j = start; j <= end; j++) { positionedGlyphs[j].x -= lineIndent; } } function align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line) { var shiftX = (justify - horizontalAlign) * maxLineLength; var shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight; for (var j = 0; j < positionedGlyphs.length; j++) { positionedGlyphs[j].x += shiftX; positionedGlyphs[j].y += shiftY; } } function shapeIcon(image, layout) { if (!image || !image.rect) return null; var dx = layout['icon-offset'][0]; var dy = layout['icon-offset'][1]; var x1 = dx - image.width / 2; var x2 = x1 + image.width; var y1 = dy - image.height / 2; var y2 = y1 + image.height; return new PositionedIcon(image, y1, y2, x1, x2); } function PositionedIcon(image, top, bottom, left, right) { this.image = image; this.top = top; this.bottom = bottom; this.left = left; this.right = right; } },{}],73:[function(require,module,exports){ 'use strict'; var BinPack = require('./bin_pack'); module.exports = SpriteAtlas; function SpriteAtlas(width, height) { this.width = width; this.height = height; this.bin = new BinPack(width, height); this.images = {}; this.data = false; this.texture = 0; // WebGL ID this.filter = 0; // WebGL ID this.pixelRatio = 1; this.dirty = true; } SpriteAtlas.prototype = { get debug() { return 'canvas' in this; }, set debug(value) { if (value && !this.canvas) { this.canvas = document.createElement('canvas'); this.canvas.width = this.width * this.pixelRatio; this.canvas.height = this.height * this.pixelRatio; this.canvas.style.width = this.width + 'px'; this.canvas.style.width = this.width + 'px'; document.body.appendChild(this.canvas); this.ctx = this.canvas.getContext('2d'); } else if (!value && this.canvas) { this.canvas.parentNode.removeChild(this.canvas); delete this.ctx; delete this.canvas; } } }; SpriteAtlas.prototype.resize = function(newRatio) { if (this.pixelRatio === newRatio) return false; var oldRatio = this.pixelRatio; this.pixelRatio = newRatio; if (this.canvas) { this.canvas.width = this.width * this.pixelRatio; this.canvas.height = this.height * this.pixelRatio; } if (this.data) { var oldData = this.data; this.data = false; this.allocate(); this.texture = false; var oldWidth = this.width * oldRatio; var oldHeight = this.height * oldRatio; var newWidth = this.width * newRatio; var newHeight = this.height * newRatio; // Basic image scaling. TODO: Replace this with better image scaling. var newImage = this.data; var oldImage = oldData; for (var y = 0; y < newHeight; y++) { var oldYOffset = Math.floor((y * oldHeight) / newHeight) * oldWidth; var newYOffset = y * newWidth; for (var x = 0; x < newWidth; x++) { var oldX = Math.floor((x * oldWidth) / newWidth); newImage[newYOffset + x] = oldImage[oldYOffset + oldX]; } } oldData = null; this.dirty = true; } return this.dirty; }; function copyBitmap(src, srcStride, srcX, srcY, dst, dstStride, dstX, dstY, width, height, wrap) { var srcI = srcY * srcStride + srcX; var dstI = dstY * dstStride + dstX; var x, y; if (wrap) { // add 1 pixel wrapped padding on each side of the image dstI -= dstStride; for (y = -1; y <= height; y++, srcI = ((y + height) % height + srcY) * srcStride + srcX, dstI += dstStride) { for (x = -1; x <= width; x++) { dst[dstI + x] = src[srcI + ((x + width) % width)]; } } } else { for (y = 0; y < height; y++, srcI += srcStride, dstI += dstStride) { for (x = 0; x < width; x++) { dst[dstI + x] = src[srcI + x]; } } } } SpriteAtlas.prototype.allocateImage = function(pixelWidth, pixelHeight) { // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them // into 2 bytes rather than 4 bytes. // Pad icons to prevent them from polluting neighbours during linear interpolation var padding = 2; var packWidth = pixelWidth + padding + (4 - (pixelWidth + padding) % 4); var packHeight = pixelHeight + padding + (4 - (pixelHeight + padding) % 4);// + 4; // We have to allocate a new area in the bin, and store an empty image in it. // Add a 1px border around every image. var rect = this.bin.allocate(packWidth, packHeight); if (rect.w === 0) { return rect; } rect.originalWidth = pixelWidth; rect.originalHeight = pixelHeight; return rect; }; SpriteAtlas.prototype.getImage = function(name, wrap) { if (this.images[name]) { return this.images[name]; } if (!this.sprite) { return null; } var pos = this.sprite.getSpritePosition(name); if (!pos.width || !pos.height) { return null; } var width = pos.width / pos.pixelRatio; var height = pos.height / pos.pixelRatio; var rect = this.allocateImage(width, height); if (rect.w === 0) { return rect; } var image = new AtlasImage(rect, width, height, pos.sdf); this.images[name] = image; this.copy(rect, pos, wrap); return image; }; SpriteAtlas.prototype.getPosition = function(name, repeating) { var image = this.getImage(name, repeating); var rect = image && image.rect; if (!rect) { return null; } // When the image is repeating, get the correct position of the image, rather than the // one rounded up to 4 pixels. var width = repeating ? image.width : rect.w; var height = repeating ? image.height : rect.h; var padding = 1; return { size: [width, height], tl: [(rect.x + padding) / this.width, (rect.y + padding) / this.height], br: [(rect.x + padding + width) / this.width, (rect.y + padding + height) / this.height] }; }; SpriteAtlas.prototype.allocate = function() { if (!this.data) { var w = Math.floor(this.width * this.pixelRatio); var h = Math.floor(this.height * this.pixelRatio); this.data = new Uint32Array(w * h); for (var i = 0; i < this.data.length; i++) { this.data[i] = 0; } } }; SpriteAtlas.prototype.copy = function(dst, src, wrap) { // if (!sprite->raster) return; if (!this.sprite.img.data) return; var srcImg = new Uint32Array(this.sprite.img.data.buffer); this.allocate(); var dstImg = this.data; var padding = 1; copyBitmap( /* source buffer */ srcImg, /* source stride */ this.sprite.img.width, /* source x */ src.x, /* source y */ src.y, /* dest buffer */ dstImg, /* dest stride */ this.width * this.pixelRatio, /* dest x */ (dst.x + padding) * this.pixelRatio, /* dest y */ (dst.y + padding) * this.pixelRatio, /* icon dimension */ src.width, /* icon dimension */ src.height, /* wrap */ wrap ); this.dirty = true; }; SpriteAtlas.prototype.setSprite = function(sprite) { this.sprite = sprite; }; SpriteAtlas.prototype.addIcons = function(icons, callback) { for (var i = 0; i < icons.length; i++) { this.getImage(icons[i]); } callback(null, this.images); }; SpriteAtlas.prototype.bind = function(gl, linear) { var first = false; if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); first = true; } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } var filterVal = linear ? gl.LINEAR : gl.NEAREST; if (filterVal !== this.filter) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterVal); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterVal); this.filter = filterVal; } if (this.dirty) { this.allocate(); if (first) { gl.texImage2D( gl.TEXTURE_2D, // enum target 0, // ind level gl.RGBA, // ind internalformat this.width * this.pixelRatio, // GLsizei width this.height * this.pixelRatio, // GLsizei height 0, // ind border gl.RGBA, // enum format gl.UNSIGNED_BYTE, // enum type new Uint8Array(this.data.buffer) // Object data ); } else { gl.texSubImage2D( gl.TEXTURE_2D, // enum target 0, // int level 0, // int xoffset 0, // int yoffset this.width * this.pixelRatio, // long width this.height * this.pixelRatio, // long height gl.RGBA, // enum format gl.UNSIGNED_BYTE, // enum type new Uint8Array(this.data.buffer) // Object pixels ); } this.dirty = false; // DEBUG if (this.ctx) { var data = this.ctx.getImageData(0, 0, this.width * this.pixelRatio, this.height * this.pixelRatio); data.data.set(new Uint8ClampedArray(this.data.buffer)); this.ctx.putImageData(data, 0, 0); this.ctx.strokeStyle = 'red'; for (var k = 0; k < this.bin.free.length; k++) { var free = this.bin.free[k]; this.ctx.strokeRect(free.x * this.pixelRatio, free.y * this.pixelRatio, free.w * this.pixelRatio, free.h * this.pixelRatio); } } // END DEBUG } }; function AtlasImage(rect, width, height, sdf) { this.rect = rect; this.width = width; this.height = height; this.sdf = sdf; } },{"./bin_pack":59}],74:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var interpolate = require('../util/interpolate'); var browser = require('../util/browser'); var LatLng = require('../geo/lat_lng'); var LatLngBounds = require('../geo/lat_lng_bounds'); var Point = require('point-geometry'); /** * @typedef {Object} CameraOptions * @property {Array} [center] Latitude and longitude (passed as `[lat, lng]`) * @property {number} [zoom] Map zoom level * @property {number} [bearing] Map rotation bearing in degrees counter-clockwise from north * @property {number} [pitch] The angle at which the camera is looking at the ground */ /** * @typedef {Object} [AnimationOptions] * @property {number} [duration=500] Number in milliseconds * @property {Function} [easing] * @property {Array} [offset=[0,0]] point, origin of movement relative to map center * @property {boolean} [animate=true] When set to false, no animation happens */ var Camera = module.exports = function() {}; util.extend(Camera.prototype, /** @lends Map.prototype */{ /** * Get the current view geographical point. * @returns {LatLng} */ getCenter: function() { return this.transform.center; }, /** * Sets a map location. Equivalent to `jumpTo({center: center})`. * * @param {Array} center Latitude and longitude (passed as `[lat, lng]`) * @fires movestart * @fires moveend * @returns {Map} `this` * @example * map.setCenter([-74, 38]); */ setCenter: function(center) { this.jumpTo({center: center}); }, /** * Pan by a certain number of pixels * * @param {Array} offset [x, y] * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ panBy: function(offset, options) { this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options)); return this; }, /** * Pan to a certain location with easing * * @param {Object} latlng a `LatLng` object * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ panTo: function(latlng, options) { this.stop(); latlng = LatLng.convert(latlng); options = util.extend({ duration: 500, easing: util.ease, offset: [0, 0] }, options); var tr = this.transform, offset = Point.convert(options.offset).rotate(-tr.angle), from = tr.point, to = tr.project(latlng).sub(offset); if (!options.noMoveStart) { this.fire('movestart'); } this._ease(function(k) { tr.center = tr.unproject(from.add(to.sub(from).mult(k))); this.fire('move'); }, function() { this.fire('moveend'); }, options); return this; }, /** * Get the current zoom * @returns {number} */ getZoom: function() { return this.transform.zoom; }, /** * Sets a map zoom. Equivalent to `jumpTo({zoom: zoom})`. * * @param {number} zoom Map zoom level * @fires movestart * @fires moveend * @returns {Map} `this` * @example * // zoom the map to 5 * map.setZoom(5); */ setZoom: function(zoom) { this.jumpTo({zoom: zoom}); }, /** * Zooms to a certain zoom level with easing. * * @param {Number} zoom * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomTo: function(zoom, options) { this.stop(); options = util.extend({ duration: 500 }, options); options.easing = this._updateEasing(options.duration, zoom, options.easing); var tr = this.transform, around = tr.center, startZoom = tr.zoom; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } if (options.animate === false) options.duration = 0; if (!this.zooming) { this.zooming = true; this.fire('movestart'); } this._ease(function(k) { tr.setZoomAround(interpolate(startZoom, zoom, k), around); this.fire('move').fire('zoom'); }, function() { this.ease = null; if (options.duration >= 200) { this.zooming = false; this.fire('moveend'); } }, options); if (options.duration < 200) { clearTimeout(this._onZoomEnd); this._onZoomEnd = setTimeout(function() { this.zooming = false; this.fire('moveend'); }.bind(this), 200); } return this; }, /** * Zoom in by 1 level * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomIn: function(options) { this.zoomTo(this.getZoom() + 1, options); }, /** * Zoom out by 1 level * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomOut: function(options) { this.zoomTo(this.getZoom() - 1, options); }, /** * Get the current bearing in degrees * @returns {number} */ getBearing: function() { return this.transform.bearing; }, /** * Sets a map rotation. Equivalent to `jumpTo({bearing: bearing})`. * * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north * @fires movestart * @fires moveend * @returns {Map} `this` * @example * // rotate the map to 90 degrees * map.setBearing(90); */ setBearing: function(bearing) { this.jumpTo({bearing: bearing}); }, /** * Rotate bearing by a certain number of degrees with easing * * @param {Number} bearing * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ rotateTo: function(bearing, options) { this.stop(); options = util.extend({ duration: 500, easing: util.ease }, options); var tr = this.transform, start = this.getBearing(), around = tr.center; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } bearing = this._normalizeBearing(bearing, start); this.rotating = true; this.fire('movestart'); this._ease(function(k) { tr.setBearingAround(interpolate(start, bearing, k), around); this.fire('move').fire('rotate'); }, function() { this.rotating = false; this.fire('moveend'); }, options); return this; }, /** * Sets map bearing to 0 (north) with easing * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ resetNorth: function(options) { return this.rotateTo(0, util.extend({duration: 1000}, options)); }, /** * Get the current angle in degrees * @returns {number} */ getPitch: function() { return this.transform.pitch; }, /** * Sets a map angle. Equivalent to `jumpTo({pitch: pitch})`. * * @param {number} pitch The angle at which the camera is looking at the ground * @fires movestart * @fires moveend * @returns {Map} `this` */ setPitch: function(pitch) { this.jumpTo({pitch: pitch}); }, /** * Zoom to contain certain geographical bounds * * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]] * @param {Object} options * @param {Number} [options.speed=1.2] How fast animation occurs * @param {Number} [options.curve=1.42] How much zooming out occurs during animation * @param {Function} options.easing * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels * @param {Number} options.maxZoom * @fires movestart * @fires moveend * @returns {this} */ fitBounds: function(bounds, options) { options = util.extend({ padding: 0, offset: [0, 0], maxZoom: Infinity }, options); bounds = LatLngBounds.convert(bounds); var offset = Point.convert(options.offset), tr = this.transform, nw = tr.project(bounds.getNorthWest()), se = tr.project(bounds.getSouthEast()), size = se.sub(nw), scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x, scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y; options.center = tr.unproject(nw.add(se).div(2)); options.zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom); options.bearing = 0; return options.linear ? this.easeTo(options) : this.flyTo(options); }, /** * Change any combination of center, zoom, bearing, and pitch, without * a transition. The map will retain the current values for any options * not included in `options`. * * @param {CameraOptions} options map view options * @fires movestart * @fires moveend * @returns {Map} `this` */ jumpTo: function(options) { this.stop(); var tr = this.transform, zoomChanged = false, bearingChanged = false, pitchChanged = false; if ('center' in options) { tr.center = LatLng.convert(options.center); } if ('zoom' in options && tr.zoom !== +options.zoom) { zoomChanged = true; tr.zoom = +options.zoom; } if ('bearing' in options && tr.bearing !== +options.bearing) { bearingChanged = true; tr.bearing = +options.bearing; } if ('pitch' in options && tr.pitch !== +options.pitch) { pitchChanged = true; tr.pitch = +options.pitch; } this.fire('movestart') .fire('move'); if (zoomChanged) { this.fire('zoom'); } if (bearingChanged) { this.fire('rotate'); } if (pitchChanged) { this.fire('pitch'); } return this.fire('moveend'); }, /** * Easing animation to a specified location/zoom/bearing * * @param {CameraOptions+AnimationOptions} options map view and animation options * @fires movestart * @fires moveend * @returns {this} */ easeTo: function(options) { this.stop(); options = util.extend({ offset: [0, 0], duration: 500, easing: util.ease }, options); var tr = this.transform, offset = Point.convert(options.offset).rotate(-tr.angle), from = tr.point, startZoom = this.getZoom(), startBearing = this.getBearing(), startPitch = this.getPitch(); var zoom = 'zoom' in options ? +options.zoom : startZoom; var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing; var pitch = 'pitch' in options ? +options.pitch : startPitch; var scale = tr.zoomScale(zoom - startZoom), to = 'center' in options ? tr.project(LatLng.convert(options.center)).sub(offset.div(scale)) : from, around; if (zoom !== startZoom) { around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale))); this.zooming = true; } if (startBearing !== bearing) { this.rotating = true; } this.fire('movestart'); this._ease(function (k) { if (zoom !== startZoom) { tr.setZoomAround(interpolate(startZoom, zoom, k), around); } else { tr.center = tr.unproject(from.add(to.sub(from).mult(k))); } if (bearing !== startBearing) { tr.bearing = interpolate(startBearing, bearing, k); } if (pitch !== startPitch) { tr.pitch = interpolate(startPitch, pitch, k); } this.fire('move'); if (this.zooming) { this.fire('zoom'); } if (this.rotating) { this.fire('rotate'); } }, function() { this.zooming = false; this.rotating = false; this.fire('moveend'); }, options); return this; }, /** * Flying animation to a specified location/zoom/bearing with automatic curve * * @param {CameraOptions} options map view options * @param {Number} [options.speed=1.2] How fast animation occurs * @param {Number} [options.curve=1.42] How much zooming out occurs during animation * @param {Function} [options.easing] * @fires movestart * @fires moveend * @returns {this} * @example * // fly with default options to null island * map.flyTo({center: [0, 0], zoom: 9}); * // using flyTo options * map.flyTo({ * center: [0, 0], * zoom: 9, * speed: 0.2, * curve: 1, * easing: function(t) { * return t; * } * }); */ flyTo: function(options) { this.stop(); options = util.extend({ offset: [0, 0], speed: 1.2, curve: 1.42, easing: util.ease }, options); var tr = this.transform, offset = Point.convert(options.offset), startZoom = this.getZoom(), startBearing = this.getBearing(); var center = 'center' in options ? LatLng.convert(options.center) : this.getCenter(); var zoom = 'zoom' in options ? +options.zoom : startZoom; var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing; var scale = tr.zoomScale(zoom - startZoom), from = tr.point, to = tr.project(center).sub(offset.div(scale)); var startWorldSize = tr.worldSize, rho = options.curve, V = options.speed, w0 = Math.max(tr.width, tr.height), w1 = w0 / scale, u1 = to.sub(from).mag(), rho2 = rho * rho; function r(i) { var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1); return Math.log(Math.sqrt(b * b + 1) - b); } function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; } function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; } function tanh(n) { return sinh(n) / cosh(n); } var r0 = r(0), w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); }, u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; }, S = (r(1) - r0) / rho; if (Math.abs(u1) < 0.000001) { if (Math.abs(w0 - w1) < 0.000001) return this; var k = w1 < w0 ? -1 : 1; S = Math.abs(Math.log(w1 / w0)) / rho; u = function() { return 0; }; w = function(s) { return Math.exp(k * rho * s); }; } options.duration = 1000 * S / V; this.zooming = true; if (startBearing !== bearing) this.rotating = true; this.fire('movestart'); this._ease(function (k) { var s = k * S, us = u(s); tr.zoom = startZoom + tr.scaleZoom(1 / w(s)); tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize); if (bearing !== startBearing) { tr.bearing = interpolate(startBearing, bearing, k); } this.fire('move').fire('zoom'); if (bearing !== startBearing) { this.fire('rotate'); } }, function() { this.zooming = false; this.rotating = false; this.fire('moveend'); }, options); return this; }, isEasing: function() { return !!this._abortFn; }, /** * Stop current animation * * @returns {this} */ stop: function() { if (this._abortFn) { this._abortFn.call(this); delete this._abortFn; this._finishFn.call(this); delete this._finishFn; } return this; }, _ease: function(frame, finish, options) { this._finishFn = finish; this._abortFn = browser.timed(function (t) { frame.call(this, options.easing(t)); if (t === 1) { delete this._abortFn; this._finishFn.call(this); delete this._finishFn; } }, options.animate === false ? 0 : options.duration, this); }, // convert bearing so that it's numerically close to the current one so that it interpolates properly _normalizeBearing: function(bearing, currentBearing) { bearing = util.wrap(bearing, -180, 180); var diff = Math.abs(bearing - currentBearing); if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360; if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360; return bearing; }, _updateEasing: function(duration, zoom, bezier) { var easing; if (this.ease) { var ease = this.ease, t = (Date.now() - ease.start) / ease.duration, speed = ease.easing(t + 0.01) - ease.easing(t), // Quick hack to make new bezier that is continuous with last x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01, y = Math.sqrt(0.27 * 0.27 - x * x); easing = util.bezier(x, y, 0.25, 1); } else { easing = bezier ? util.bezier.apply(util, bezier) : util.ease; } // store information on current easing this.ease = { start: (new Date()).getTime(), to: Math.pow(2, zoom), duration: duration, easing: easing }; return easing; } }); },{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../util/browser":85,"../util/interpolate":92,"../util/util":96,"point-geometry":113}],75:[function(require,module,exports){ 'use strict'; var Control = require('./control'); var DOM = require('../../util/dom'); var util = require('../../util/util'); module.exports = Attribution; /** * Creates an attribution control * @class Attribution * @example * map.addControl(new mapboxgl.Attribution()); */ function Attribution() {} Attribution.prototype = util.inherit(Control, { options: { position: 'bottom-right' }, onAdd: function(map) { var className = 'mapboxgl-ctrl-attrib', container = this._container = DOM.create('div', className, map.getContainer()); this._update(); map.on('source.load', this._update.bind(this)); map.on('source.change', this._update.bind(this)); map.on('source.remove', this._update.bind(this)); map.on('moveend', this._updateEditLink.bind(this)); return container; }, _update: function() { var attributions = []; if (this._map.style) { for (var id in this._map.style.sources) { var source = this._map.style.sources[id]; if (source.attribution && attributions.indexOf(source.attribution) < 0) { attributions.push(source.attribution); } } } this._container.innerHTML = attributions.join(' | '); this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0]; this._updateEditLink(); }, _updateEditLink: function() { if (this._editLink) { var center = this._map.getCenter(); this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' + center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1); } } }); },{"../../util/dom":88,"../../util/util":96,"./control":76}],76:[function(require,module,exports){ 'use strict'; module.exports = Control; /** * A base class for map-related interface elements. * * @class Control */ function Control() {} Control.prototype = { /** * Add this control to the map, returning the control itself * for chaining. This will insert the control's DOM element into * the map's DOM element if the control has a `position` specified. * * @param {Map} map * @returns {Control} this */ addTo: function(map) { this._map = map; var container = this._container = this.onAdd(map); if (this.options && this.options.position) { var pos = this.options.position; var corner = map._controlCorners[pos]; container.className += ' mapboxgl-ctrl'; if (pos.indexOf('bottom') !== -1) { corner.insertBefore(container, corner.firstChild); } else { corner.appendChild(container); } } return this; }, /** * Remove this control from the map it has been added to. * * @returns {Control} this */ remove: function() { this._container.parentNode.removeChild(this._container); if (this.onRemove) this.onRemove(this._map); this._map = null; return this; } }; },{}],77:[function(require,module,exports){ 'use strict'; var Control = require('./control'); var DOM = require('../../util/dom'); var util = require('../../util/util'); module.exports = Navigation; /** * Creates a navigation control with zoom buttons and a compass * @class Navigation * @param {Object} [options] * @param {String} [options.position=top-right] A string indicating the control's position on the map. Options are `top-right`, `top-left`, `bottom-right`, `bottom-left` * @example * map.addControl(new mapboxgl.Navigation({position: 'top-left'})); // position is optional */ function Navigation(options) { util.setOptions(this, options); } Navigation.prototype = util.inherit(Control, { options: { position: 'top-right' }, onAdd: function(map) { var className = 'mapboxgl-ctrl'; var container = this._container = DOM.create('div', className + '-group', map.getContainer()); this._zoomInButton = this._createButton(className + '-icon ' + className + '-zoom-in', map.zoomIn.bind(map)); this._zoomOutButton = this._createButton(className + '-icon ' + className + '-zoom-out', map.zoomOut.bind(map)); this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map)); var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass); compassCanvas.style.cssText = 'width:30px; height:30px;'; compassCanvas.width = 26 * 2; compassCanvas.height = 26 * 2; this._compass.addEventListener('mousedown', this._onCompassDown.bind(this)); this._onCompassMove = this._onCompassMove.bind(this); this._onCompassUp = this._onCompassUp.bind(this); this._compassCtx = compassCanvas.getContext('2d'); map.on('rotate', this._drawNorth.bind(this)); this._drawNorth(); return container; }, _onCompassDown: function(e) { DOM.disableDrag(); document.addEventListener('mousemove', this._onCompassMove); document.addEventListener('mouseup', this._onCompassUp); this._prevX = e.screenX; e.stopPropagation(); }, _onCompassMove: function(e) { var x = e.screenX, d = x < 2 ? -5 : // left edge of the screen, continue rotating x > window.screen.width - 2 ? 5 : // right edge (x - this._prevX) / 4; this._map.setBearing(this._map.getBearing() - d); this._prevX = e.screenX; this._moved = true; e.preventDefault(); }, _onCompassUp: function() { document.removeEventListener('mousemove', this._onCompassMove); document.removeEventListener('mouseup', this._onCompassUp); DOM.enableDrag(); if (this._moved) { this._moved = false; DOM.suppressClick(); } }, _createButton: function(className, fn) { var a = DOM.create('button', className, this._container); a.addEventListener('click', function() { fn(); }); return a; }, _drawNorth: function() { var rad = 20, width = 8, center = 26, angle = this._map.transform.angle + (Math.PI / 2), ctx = this._compassCtx; this._compassCanvas.width = this._compassCanvas.width; ctx.translate(center, center); ctx.rotate(angle); ctx.beginPath(); ctx.fillStyle = '#000'; ctx.lineTo(0, -width); ctx.lineTo(-rad, 0); ctx.lineTo(0, width); ctx.fill(); ctx.beginPath(); ctx.fillStyle = '#bbb'; ctx.moveTo(0, 0); ctx.lineTo(0, width); ctx.lineTo(rad, 0); ctx.lineTo(0, -width); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = '#fff'; ctx.lineWidth = 4; ctx.moveTo(0, -width); ctx.lineTo(0, width); ctx.stroke(); } }); },{"../../util/dom":88,"../../util/util":96,"./control":76}],78:[function(require,module,exports){ 'use strict'; var Interaction = require('./interaction'); var Point = require('point-geometry'); var util = require('../util/util'); var DOM = require('../util/dom'); var LatLngBounds = require('../geo/lat_lng_bounds'); module.exports = Handlers; function Handlers(map) { var rotateEnd; var box; var inertiaLinearity = 0.2, inertiaEasing = util.bezier(0, 0, inertiaLinearity, 1); function boxzoomFinish() { if (box) { box.parentNode.removeChild(box); map.getContainer().classList.remove('mapboxgl-crosshair'); box = false; DOM.enableDrag(); } } this.interaction = new Interaction(map.getCanvas()) .on('click', function(e) { e.latLng = map.unproject(e.point); map.fire('click', e); }) .on('dblclick', function(e) { e.latLng = map.unproject(e.point); map.fire('dblclick', e); }) .on('mousemove', function(e) { e.latLng = map.unproject(e.point); map.fire('mousemove', e); }) .on('down', function() { map.fire('movestart'); }) .on('resize', function() { map.stop(); map.resize(); map.update(); }) .on('keydown', function(e) { if (e.altKey || e.ctrlKey || e.metaKey) return; var pan = 80; var rotate = 2; function zoomBy(z) { map.zoomTo(Math.round(map.getZoom()) + (e.shiftKey ? 2 : 1) * z); } function panBy(v) { map.panBy(v); } function rotateBy(v) { map.setBearing(map.getBearing() + v); } switch (e.keyCode) { case 61: case 107: case 171: case 187: zoomBy(1); break; case 189: case 109: case 173: zoomBy(-1); break; case 37: if (e.shiftKey) { rotateBy(-rotate); } else { panBy([-pan, 0]); } break; case 39: if (e.shiftKey) { rotateBy(rotate); } else { panBy([pan, 0]); } break; case 38: panBy([0, -pan]); break; case 40: panBy([0, pan]); break; default: return; } }) .on('pan', function(e) { map.stop(); var mouseLocation = map.transform.pointLocation(e.point.add(e.offset)); map.transform.setLocationAtPoint(mouseLocation, e.point); map.fire('move'); }) .on('panend', function(e) { if (!e.inertia) { map.fire('moveend'); } else { // convert velocity to px/s & adjust for increased initial animation speed when easing out var velocity = e.inertia.mult(1000 * inertiaLinearity), speed = velocity.mag(); var maxSpeed = 4000; // px/s if (speed >= maxSpeed) { speed = maxSpeed; velocity._unit()._mult(maxSpeed); } var deceleration = 8000, // px/s^2 duration = speed / (deceleration * inertiaLinearity), offset = velocity.mult(-duration / 2).round(); map.panBy(offset, { duration: duration * 1000, easing: inertiaEasing, noMoveStart: true }); } }) .on('zoom', function(e) { // Scale by sigmoid of scroll wheel delta. var scale = 2 / (1 + Math.exp(-Math.abs(e.delta / 100))); if (e.delta < 0 && scale !== 0) scale = 1 / scale; var fromScale = map.ease && isFinite(e.delta) ? map.ease.to : map.transform.scale, duration = !isFinite(e.delta) ? 800 : 0; map.zoomTo(map.transform.scaleZoom(fromScale * scale), { duration: duration, around: map.unproject(e.point) }); }) .on('rotate', function(e) { var center = map.transform.centerPoint, // Center of rotation startToCenter = e.start.sub(center), startToCenterDist = startToCenter.mag(); map.rotating = true; // If the first click was too close to the center, move the center of rotation by 200 pixels // in the direction of the click. if (startToCenterDist < 200) { center = e.start.add(new Point(-200, 0)._rotate(startToCenter.angle())); } var bearingDiff = e.prev.sub(center).angleWith(e.current.sub(center)) / Math.PI * 180; map.transform.bearing = map.getBearing() - bearingDiff; map.fire('move').fire('rotate'); window.clearTimeout(rotateEnd); rotateEnd = window.setTimeout(function() { map.rotating = false; map._rerender(); }, 200); }) .on('boxzoomstart', function(e) { if (!box) { box = DOM.create('div', 'mapboxgl-boxzoom', map.getContainer()); map.getContainer().classList.add('mapboxgl-crosshair'); map.fire('boxzoomstart'); DOM.disableDrag(); } var minX = Math.min(e.start.x, e.current.x); var maxX = Math.max(e.start.x, e.current.x); var minY = Math.min(e.start.y, e.current.y); var maxY = Math.max(e.start.y, e.current.y); DOM.setTransform(box, 'translate(' + minX + 'px,' + minY + 'px)'); box.style.width = (maxX - minX) + 'px'; box.style.height = (maxY - minY) + 'px'; }) .on('boxzoomend', function(e) { boxzoomFinish(); var bounds = new LatLngBounds( map.unproject(e.start), map.unproject(e.current) ); map.fitBounds(bounds, { linear: true }).fire('boxzoomend', { boxZoomBounds: bounds }); }) .on('boxzoomcancel', boxzoomFinish); } },{"../geo/lat_lng_bounds":19,"../util/dom":88,"../util/util":96,"./interaction":80,"point-geometry":113}],79:[function(require,module,exports){ 'use strict'; /* * Adds positional coordinates to URL hashes. Passed as an option to the map object * * @class mapboxgl.Hash * @returns {Hash} `this` */ module.exports = Hash; var util = require('../util/util'); function Hash() { util.bindAll([ '_onHashChange', '_updateHash' ], this); } Hash.prototype = { /* Map element to listen for coordinate changes * * @param {Object} map * @returns {Hash} `this` */ addTo: function(map) { this._map = map; window.addEventListener('hashchange', this._onHashChange, false); this._map.on('moveend', this._updateHash); return this; }, /* Removes hash * * @returns {Popup} `this` */ remove: function() { window.removeEventListener('hashchange', this._onHashChange, false); this._map.off('moveend', this._updateHash); delete this._map; return this; }, _onHashChange: function() { var loc = location.hash.replace('#', '').split('/'); if (loc.length >= 3) { this._map.jumpTo({ center: [+loc[1], +loc[2]], zoom: +loc[0], bearing: +(loc[3] || 0) }); return true; } return false; }, _updateHash: function() { var center = this._map.getCenter(), zoom = this._map.getZoom(), bearing = this._map.getBearing(), precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)), hash = '#' + (Math.round(zoom * 100) / 100) + '/' + center.lat.toFixed(precision) + '/' + center.lng.toFixed(precision) + (bearing ? '/' + (Math.round(bearing * 10) / 10) : ''); window.history.replaceState('', '', hash); } }; },{"../util/util":96}],80:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented'); var browser = require('../util/browser'); var Point = require('point-geometry'); module.exports = Interaction; /** * Mouse event * * @event Map#mousemove * @type {Object} * @property {Point} point the pixel location of the event * @property {Event} originalEvent the original DOM event */ /** * Double click event. * * @event Map#dblclick * @type {Object} * @property {Point} point the pixel location of the event */ /** * Pan event * * @event Map#pan * @type {Object} * @property {Point} point the pixel location of the event * @property {Point} offset a point representing the movement from the previous map location to the current one. */ /** * Pan end event * * @event Map#panend * @type {Object} * @property {number} velocity a measure of how much inertia was recorded in this pan motion */ function Interaction(el) { var interaction = this; if (!el) return; var rotating = false, panned = false, boxzoom = false, firstPos = null, pos = null, inertia = null, now; function mousePos(e) { var rect = el.getBoundingClientRect(); return new Point( e.clientX - rect.left - el.clientLeft, e.clientY - rect.top - el.clientTop); } el.addEventListener('contextmenu', function(ev) { rotating = true; firstPos = pos = mousePos(ev); ev.preventDefault(); }, false); el.addEventListener('mousedown', onmousedown, false); document.addEventListener('mouseup', onmouseup, false); document.addEventListener('mousemove', onmousemove, false); el.addEventListener('click', onclick, false); scrollwheel(zoom); el.addEventListener('dblclick', ondoubleclick, false); window.addEventListener('resize', resize, false); el.addEventListener('keydown', keydown, false); function zoom(type, delta, point) { interaction.fire('zoom', { source: type, delta: delta, point: point }); inertia = null; now = null; } function click(point, ev) { interaction.fire('click', {point: point, originalEvent: ev}); } function mousemove(point, ev) { interaction.fire('mousemove', {point: point, originalEvent: ev}); } function pan(point) { if (pos) { var offset = pos.sub(point); interaction.fire('pan', {offset: offset, point: point}); // add an averaged version of this movement to the inertia vector if (inertia) { var duration = Date.now() - now; // sometimes it's 0 after some erratic paning if (duration) { var time = duration + now; inertia.push([time, point]); while (inertia.length > 2 && time - inertia[0][0] > 100) inertia.shift(); } } else { inertia = []; } now = Date.now(); pos = point; } } function resize() { interaction.fire('resize'); } function keydown(ev) { if (boxzoom && ev.keyCode === 27) { interaction.fire('boxzoomcancel'); boxzoom = false; } interaction.fire('keydown', ev); } function rotate(point) { if (pos) { interaction.fire('rotate', { start: firstPos, prev: pos, current: point }); pos = point; } } function doubleclick(point, ev) { interaction.fire('dblclick', { point: point, originalEvent: ev }); } function onmousedown(ev) { firstPos = pos = mousePos(ev); interaction.fire('down'); if (ev.shiftKey || ((ev.which === 1) && (ev.button === 1))) { boxzoom = true; } } function onmouseup(ev) { panned = pos && firstPos && (pos.x !== firstPos.x || pos.y !== firstPos.y); rotating = false; pos = null; if (boxzoom) { interaction.fire('boxzoomend', { start: firstPos, current: mousePos(ev) }); boxzoom = false; } else if (inertia && inertia.length >= 2 && now > Date.now() - 100) { var last = inertia[inertia.length - 1], first = inertia[0], velocity = last[1].sub(first[1]).div(last[0] - first[0]); interaction.fire('panend', {inertia: velocity}); } else if (pos) { interaction.fire('panend'); } inertia = null; now = null; } function onmousemove(ev) { var point = mousePos(ev); if (boxzoom) { interaction.fire('boxzoomstart', { start: firstPos, current: point }); } else if (rotating) { rotate(point); } else if (pos) { pan(point); } else { var target = ev.toElement || ev.target; while (target && target !== el && target.parentNode) target = target.parentNode; if (target === el) { mousemove(point, ev); } } } function onclick(ev) { if (!panned) click(mousePos(ev), ev); } function ondoubleclick(ev) { doubleclick(mousePos(ev), ev); zoom('wheel', Infinity * (ev.shiftKey ? -1 : 1), mousePos(ev)); ev.preventDefault(); } function scrollwheel(callback) { var firefox = /Firefox/i.test(navigator.userAgent); var safari = /Safari/i.test(navigator.userAgent) && !/Chrom(ium|e)/i.test(navigator.userAgent); var time = window.performance || Date; el.addEventListener('wheel', wheel, false); el.addEventListener('mousewheel', mousewheel, false); var lastEvent = 0; var type = null; var typeTimeout = null; var initialValue = null; function scroll(value, ev) { var stamp = time.now(); var timeDelta = stamp - lastEvent; lastEvent = stamp; var point = mousePos(ev); if (value !== 0 && (value % 4.000244140625) === 0) { // This one is definitely a mouse wheel event. type = 'wheel'; // Normalize this value to match trackpad. value = Math.floor(value / 4); } else if (value !== 0 && Math.abs(value) < 4) { // This one is definitely a trackpad event because it is so small. type = 'trackpad'; } else if (timeDelta > 400) { // This is likely a new scroll action. type = null; initialValue = value; // Start a timeout in case this was a singular event, and dely it // by up to 40ms. typeTimeout = setTimeout(function() { type = 'wheel'; callback(type, -initialValue, point); }, 40); } else if (type === null) { // This is a repeating event, but we don't know the type of event // just yet. If the delta per time is small, we assume it's a // fast trackpad; otherwise we switch into wheel mode. type = (Math.abs(timeDelta * value) < 200) ? 'trackpad' : 'wheel'; // Make sure our delayed event isn't fired again, because we // accumulate the previous event (which was less than 40ms ago) into // this event. if (typeTimeout) { clearTimeout(typeTimeout); typeTimeout = null; value += initialValue; } } // Slow down zoom if shift key is held for more precise zooming if (ev.shiftKey && value) value = value / 4; // Only fire the callback if we actually know what type of scrolling // device the user uses. if (type !== null) { callback(type, -value, point); } } function wheel(e) { var deltaY = e.deltaY; // Firefox doubles the values on retina screens... if (firefox && e.deltaMode === window.WheelEvent.DOM_DELTA_PIXEL) deltaY /= browser.devicePixelRatio; if (e.deltaMode === window.WheelEvent.DOM_DELTA_LINE) deltaY *= 40; scroll(deltaY, e); e.preventDefault(); } function mousewheel(e) { var deltaY = -e.wheelDeltaY; if (safari) deltaY = deltaY / 3; scroll(deltaY, e); e.preventDefault(); } } } Interaction.prototype = Object.create(Evented); },{"../util/browser":85,"../util/evented":90,"point-geometry":113}],81:[function(require,module,exports){ 'use strict'; var Canvas = require('../util/canvas'); var util = require('../util/util'); var browser = require('../util/browser'); var Evented = require('../util/evented'); var DOM = require('../util/dom'); var Style = require('../style/style'); var AnimationLoop = require('../style/animation_loop'); var Painter = require('../render/painter'); var Transform = require('../geo/transform'); var Hash = require('./hash'); var Handlers = require('./handlers'); var Camera = require('./camera'); var LatLng = require('../geo/lat_lng'); var LatLngBounds = require('../geo/lat_lng_bounds'); var Point = require('point-geometry'); var Attribution = require('./control/attribution'); /** * Creates a map instance. * @class Map * @param {Object} options * @param {String} options.container HTML element to initialize the map in (or element id as string) * @param {Number} [options.minZoom=0] Minimum zoom of the map * @param {Number} [options.maxZoom=20] Maximum zoom of the map * @param {Object} options.style Map style and data source definition (either a JSON object or a JSON URL), described in the [style reference](https://mapbox.com/mapbox-gl-style-spec/) * @param {Boolean} [options.hash=false] If `true`, the map will track and update the page URL according to map position * @param {Boolean} [options.interactive=true] If `false`, no mouse, touch, or keyboard listeners are attached to the map, so it will not respond to input * @param {Array} options.classes Style class names with which to initialize the map * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected. * @param {Boolean} [options.preserveDrawingBuffer=false] If `true`, The maps canvas can be exported to a PNG using `map.getCanvas().toDataURL();`. This is false by default as a performance optimization. * @example * var map = new mapboxgl.Map({ * container: 'map', * center: [37.772537, -122.420679], * zoom: 13, * style: style_object, * hash: true * }); */ var Map = module.exports = function(options) { options = this.options = util.inherit(this.options, options); this.animationLoop = new AnimationLoop(); this.transform = new Transform(options.minZoom, options.maxZoom); if (options.maxBounds) { var b = LatLngBounds.convert(options.maxBounds); this.transform.latRange = [b.getSouth(), b.getNorth()]; this.transform.lngRange = [b.getWest(), b.getEast()]; } util.bindAll([ '_forwardStyleEvent', '_forwardSourceEvent', '_forwardLayerEvent', '_forwardTileEvent', '_onStyleLoad', '_onStyleChange', '_onSourceAdd', '_onSourceRemove', '_onSourceUpdate', 'update', 'render' ], this); this._setupContainer(); this._setupPainter(); this.on('move', this.update); this.on('zoom', this.update.bind(this, true)); this.on('moveend', function() { this.animationLoop.set(300); // text fading this._rerender(); }.bind(this)); this.handlers = options.interactive && new Handlers(this); this._hash = options.hash && (new Hash()).addTo(this); // don't set position from options if set through hash if (!this._hash || !this._hash._onHashChange()) { this.jumpTo(options); } this.sources = {}; this.stacks = {}; this._classes = {}; this.resize(); if (options.classes) this.setClasses(options.classes); if (options.style) this.setStyle(options.style); if (options.attributionControl) this.addControl(new Attribution()); }; util.extend(Map.prototype, Evented); util.extend(Map.prototype, Camera.prototype); util.extend(Map.prototype, /** @lends Map.prototype */{ options: { center: [0, 0], zoom: 0, bearing: 0, pitch: 0, minZoom: 0, maxZoom: 20, interactive: true, hash: false, attributionControl: true, failIfMajorPerformanceCaveat: false, preserveDrawingBuffer: false }, addControl: function(control) { control.addTo(this); return this; }, /** * @typedef {Object} [styleOptions] * @param {Boolean} [styleOptions.transition=true] */ /** * Adds a style class to a map * * @param {string} klass name of style class * @param {styleOptions} options * @fires change * @returns {Map} `this` */ addClass: function(klass, options) { if (this._classes[klass]) return; this._classes[klass] = true; if (this.style) this.style._cascade(this._classes, options); }, /** * Removes a style class from a map * * @param {string} klass name of style class * @param {styleOptions} options * @fires change * @returns {Map} `this` */ removeClass: function(klass, options) { if (!this._classes[klass]) return; delete this._classes[klass]; if (this.style) this.style._cascade(this._classes, options); }, /** * Helper method to add more than one class * * @param {Array<string>} klasses An array of class names * @param {styleOptions} options * @fires change * @returns {Map} `this` */ setClasses: function(klasses, options) { this._classes = {}; for (var i = 0; i < klasses.length; i++) { this._classes[klasses[i]] = true; } if (this.style) this.style._cascade(this._classes, options); }, /** * Check whether a style class is active * * @param {string} klass Name of style class * @returns {boolean} */ hasClass: function(klass) { return !!this._classes[klass]; }, /** * Return an array of the current active style classes * * @returns {boolean} */ getClasses: function() { return Object.keys(this._classes); }, /** * Detect the map's new width and height and resize it. * * @returns {Map} `this` */ resize: function() { var width = 0, height = 0; if (this._container) { width = this._container.offsetWidth || 400; height = this._container.offsetHeight || 300; } this._canvas.resize(width, height); this.transform.width = width; this.transform.height = height; this.transform._constrain(); this.painter.resize(width, height); return this .fire('movestart') .fire('move') .fire('resize') .fire('moveend'); }, /** * Get the map's geographical bounds * * @returns {LatLngBounds} */ getBounds: function() { return new LatLngBounds( this.transform.pointLocation(new Point(0, 0)), this.transform.pointLocation(this.transform.size)); }, /** * Get pixel coordinates (relative to map container) given a geographical location * * @param {LatLng} latlng * @returns {Object} `x` and `y` coordinates */ project: function(latlng) { return this.transform.locationPoint(LatLng.convert(latlng)); }, /** * Get geographical coordinates given pixel coordinates * * @param {Array<number>} point [x, y] pixel coordinates * @returns {LatLng} */ unproject: function(point) { return this.transform.pointLocation(Point.convert(point)); }, /** * Get all features at a point ([x, y]) * * @param {Array<number>} point [x, y] pixel coordinates * @param {Object} params * @param {number} [params.radius=0] Optional. Radius in pixels to search in * @param {string} params.layer Optional. Only return features from a given layer * @param {string} params.type Optional. Either `raster` or `vector` * @param {featuresAtCallback} callback function that returns the response * * @callback featuresAtCallback * @param {Object|null} err Error _If any_ * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt` * * @returns {Map} `this` * * @example * map.featuresAt([10, 20], { radius: 10 }, function(err, features) { * console.log(features); * }); */ featuresAt: function(point, params, callback) { var coord = this.transform.pointCoordinate(Point.convert(point)); this.style.featuresAt(coord, params, callback); return this; }, /** * Replaces the map's style object * * @param {Object} style A style object formatted as JSON * @returns {Map} `this` */ setStyle: function(style) { if (this.style) { this.style .off('load', this._onStyleLoad) .off('error', this._forwardStyleEvent) .off('change', this._onStyleChange) .off('source.add', this._onSourceAdd) .off('source.remove', this._onSourceRemove) .off('source.load', this._onSourceUpdate) .off('source.error', this._forwardSourceEvent) .off('source.change', this._onSourceUpdate) .off('layer.add', this._forwardLayerEvent) .off('layer.remove', this._forwardLayerEvent) .off('tile.add', this._forwardTileEvent) .off('tile.remove', this._forwardTileEvent) .off('tile.load', this.update) .off('tile.error', this._forwardTileEvent) ._remove(); this.off('rotate', this.style._redoPlacement); this.off('pitch', this.style._redoPlacement); } if (!style) { this.style = null; return this; } else if (style instanceof Style) { this.style = style; } else { this.style = new Style(style, this.animationLoop); } this.style .on('load', this._onStyleLoad) .on('error', this._forwardStyleEvent) .on('change', this._onStyleChange) .on('source.add', this._onSourceAdd) .on('source.remove', this._onSourceRemove) .on('source.load', this._onSourceUpdate) .on('source.error', this._forwardSourceEvent) .on('source.change', this._onSourceUpdate) .on('layer.add', this._forwardLayerEvent) .on('layer.remove', this._forwardLayerEvent) .on('tile.add', this._forwardTileEvent) .on('tile.remove', this._forwardTileEvent) .on('tile.load', this.update) .on('tile.error', this._forwardTileEvent); this.on('rotate', this.style._redoPlacement); this.on('pitch', this.style._redoPlacement); return this; }, /** * Add a source to the map style. * * @param {string} id ID of the source. Must not be used by any existing source. * @param {Object} source source specification, following the * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources) * @fires source.add * @returns {Map} `this` */ addSource: function(id, source) { this.style.addSource(id, source); return this; }, /** * Remove an existing source from the map style. * * @param {string} id ID of the source to remove * @fires source.remove * @returns {Map} `this` */ removeSource: function(id) { this.style.removeSource(id); return this; }, /** * Return the style source object with the given `id`. * * @param {string} id source ID * @returns {Object} */ getSource: function(id) { return this.style.getSource(id); }, /** * Add a layer to the map style. The layer will be inserted before the layer with * ID `before`, or appended if `before` is omitted. * @param {StyleLayer|Object} layer * @param {string=} before ID of an existing layer to insert before * @fires layer.add * @returns {Map} `this` */ addLayer: function(layer, before) { this.style.addLayer(layer, before); this.style._cascade(this._classes); return this; }, /** * Remove the layer with the given `id` from the map. Any layers which refer to the * specified layer via a `ref` property are also removed. * * @param {string} id layer id * @fires layer.remove * @returns {Map} this */ removeLayer: function(id) { this.style.removeLayer(id); this.style._cascade(this._classes); return this; }, /** * Set the filter for a given style layer. * * @param {string} layer ID of a layer * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter) * @returns {Map} `this` */ setFilter: function(layer, filter) { this.style.setFilter(layer, filter); return this; }, /** * Get the filter for a given style layer. * * @param {string} layer ID of a layer * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter) */ getFilter: function(layer) { return this.style.getFilter(layer); }, /** * Set the value of a paint property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a paint property * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * @param {string=} klass optional class specifier for the property * @returns {Map} `this` */ setPaintProperty: function(layer, name, value, klass) { this.style.setPaintProperty(layer, name, value, klass); this.style._cascade(this._classes); this.update(true); return this; }, /** * Get the value of a paint property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a paint property * @param {string=} klass optional class specifier for the property * @returns {*} value for the paint propery */ getPaintProperty: function(layer, name, klass) { return this.style.getPaintProperty(layer, name, klass); }, /** * Set the value of a layout property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a layout property * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * @returns {Map} `this` */ setLayoutProperty: function(layer, name, value) { this.style.setLayoutProperty(layer, name, value); return this; }, /** * Get the value of a layout property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a layout property * @param {string=} klass optional class specifier for the property * @returns {*} value for the layout propery */ getLayoutProperty: function(layer, name) { return this.style.getLayoutProperty(layer, name); }, /** * Get the Map's container as an HTML element * @returns {HTMLElement} container */ getContainer: function() { return this._container; }, /** * Get the container for the map `canvas` element. * * If you want to add non-GL overlays to the map, you should append them to this element. This * is the element to which event bindings for map interactivity such as panning and zooming are * attached. It will receive bubbled events for child elements such as the `canvas`, but not for * map controls. * * @returns {HTMLElement} container */ getCanvasContainer: function() { return this._canvasContainer; }, /** * Get the Map's canvas as an HTML canvas * @returns {HTMLElement} canvas */ getCanvas: function() { return this._canvas.getElement(); }, _setupContainer: function() { var id = this.options.container; var container = this._container = typeof id === 'string' ? document.getElementById(id) : id; container.classList.add('mapboxgl-map'); var canvasContainer = this._canvasContainer = DOM.create('div', 'mapboxgl-canvas-container', container); if (this.options.interactive) { canvasContainer.classList.add('mapboxgl-interactive'); } this._canvas = new Canvas(this, canvasContainer); var controlContainer = DOM.create('div', 'mapboxgl-control-container', container); var corners = this._controlCorners = {}; ['top-left', 'top-right', 'bottom-left', 'bottom-right'].forEach(function (pos) { corners[pos] = DOM.create('div', 'mapboxgl-ctrl-' + pos, controlContainer); }); }, _setupPainter: function() { var gl = this._canvas.getWebGLContext({ failIfMajorPerformanceCaveat: this.options.failIfMajorPerformanceCaveat, preserveDrawingBuffer: this.options.preserveDrawingBuffer }); if (!gl) { console.error('Failed to initialize WebGL'); return; } this.painter = new Painter(gl, this.transform); }, _contextLost: function(event) { event.preventDefault(); if (this._frameId) { browser.cancelFrame(this._frameId); } }, _contextRestored: function() { this._setupPainter(); this.resize(); this.update(); }, /** * Is this map fully loaded? If the style isn't loaded * or it has a change to the sources or style that isn't * propagated to its style, return false. * * @returns {boolean} whether the map is loaded */ loaded: function() { if (this._styleDirty || this._sourcesDirty) return false; if (this.style && !this.style.loaded()) return false; return true; }, /** * Update this map's style and re-render the map. * * @param {Object} updateStyle new style * @returns {Map} this */ update: function(updateStyle) { if (!this.style) return this; this._styleDirty = this._styleDirty || updateStyle; this._sourcesDirty = true; this._rerender(); return this; }, /** * Call when a (re-)render of the map is required, e.g. when the * user panned or zoomed,f or new data is available. * @returns {Map} this */ render: function() { if (this.style && this._styleDirty) { this._styleDirty = false; this.style._recalculate(this.transform.zoom); } if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) { this._sourcesDirty = false; this._sourcesDirtyTimeout = setTimeout(function() { this._sourcesDirtyTimeout = null; }.bind(this), 50); this.style._updateSources(this.transform); } this.painter.render(this.style, { debug: this.debug, vertices: this.vertices, rotating: this.rotating, zooming: this.zooming }); this.fire('render'); if (this.loaded() && !this._loaded) { this._loaded = true; this.fire('load'); } this._frameId = null; if (!this.animationLoop.stopped()) { this._styleDirty = true; } if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) { this._rerender(); } return this; }, /** * Destroys the map's underlying resources, including web workers. * @returns {Map} this */ remove: function() { if (this._hash) this._hash.remove(); browser.cancelFrame(this._frameId); clearTimeout(this._sourcesDirtyTimeout); this.setStyle(null); return this; }, _rerender: function() { if (this.style && !this._frameId) { this._frameId = browser.frame(this.render); } }, _forwardStyleEvent: function(e) { this.fire('style.' + e.type, util.extend({style: e.target}, e)); }, _forwardSourceEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _forwardLayerEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _forwardTileEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _onStyleLoad: function(e) { this.style._cascade(this._classes, {transition: false}); this._forwardStyleEvent(e); }, _onStyleChange: function(e) { this.update(true); this._forwardStyleEvent(e); }, _onSourceAdd: function(e) { var source = e.source; if (source.onAdd) source.onAdd(this); this._forwardSourceEvent(e); }, _onSourceRemove: function(e) { var source = e.source; if (source.onRemove) source.onRemove(this); this._forwardSourceEvent(e); }, _onSourceUpdate: function(e) { this.update(); this._forwardSourceEvent(e); } }); util.extendAll(Map.prototype, { /** * Enable debugging mode * * @name debug * @memberof Map * @type {boolean} */ _debug: false, get debug() { return this._debug; }, set debug(value) { this._debug = value; this.update(); }, /** * Show collision boxes: useful for debugging label placement * in styles. * * @name collisionDebug * @memberof Map * @type {boolean} */ _collisionDebug: false, get collisionDebug() { return this._collisionDebug; }, set collisionDebug(value) { this._collisionDebug = value; for (var i in this.style.sources) { if (this.style.sources[i].reload) { this.style.sources[i].reload(); } } this.update(); }, /** * Enable continuous repaint to analyze performance * * @name repaint * @memberof Map * @type {boolean} */ _repaint: false, get repaint() { return this._repaint; }, set repaint(value) { this._repaint = value; this.update(); }, // show vertices _vertices: false, get vertices() { return this._vertices; }, set vertices(value) { this._vertices = value; this.update(); } }); },{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../geo/transform":20,"../render/painter":34,"../style/animation_loop":47,"../style/style":52,"../util/browser":85,"../util/canvas":86,"../util/dom":88,"../util/evented":90,"../util/util":96,"./camera":74,"./control/attribution":75,"./handlers":78,"./hash":79,"point-geometry":113}],82:[function(require,module,exports){ 'use strict'; module.exports = Popup; var util = require('../util/util'); var Evented = require('../util/evented'); var DOM = require('../util/dom'); var LatLng = require('../geo/lat_lng'); /** * Creates a popup component * @class Popup * @param {Object} options * @param {Boolean} options.closeButton * @param {Boolean} options.closeOnClick * @example * var tooltip = new mapboxgl.Popup() * .setLatLng(map.unproject(e.point)) * .setHTML("<h1>Hello World!</h1>") * .addTo(map); */ function Popup(options) { util.setOptions(this, options); util.bindAll([ '_updatePosition', '_onClickClose'], this); } Popup.prototype = util.inherit(Evented, /** @lends Popup.prototype */{ options: { closeButton: true, closeOnClick: true }, /** * Attaches the popup to a map * @param {Map} map * @returns {Popup} `this` */ addTo: function(map) { this._map = map; this._map.on('move', this._updatePosition); if (this.options.closeOnClick) { this._map.on('click', this._onClickClose); } this._update(); return this; }, /** * Removes the popup from the map * @example * var popup = new mapboxgl.Popup().addTo(map); * popup.remove(); * @returns {Popup} `this` */ remove: function() { if (this._container) { this._container.parentNode.removeChild(this._container); } if (this._map) { this._map.off('move', this._updatePosition); this._map.off('click', this._onClickClose); delete this._map; } return this; }, /** * Get the current coordinates of popup element relative to map * @returns {LatLng} */ getLatLng: function() { return this._latLng; }, /** * Set the coordinates of a popup element to a map * @param {LatLng} latlng * @returns {Popup} `this` */ setLatLng: function(latlng) { this._latLng = LatLng.convert(latlng); this._update(); return this; }, /** * Fill a popup element with text only content * @param {string} text * @returns {Popup} `this` */ setText: function(text) { this._content = document.createTextNode(text); this._updateContent(); return this; }, /** * Fill a popup element with HTML content * @param {string} html * @returns {Popup} `this` */ setHTML: function(html) { this._content = document.createDocumentFragment(); var temp = document.createElement('body'), child; temp.innerHTML = html; while (true) { child = temp.firstChild; if (!child) break; this._content.appendChild(child); } this._updateContent(); return this; }, _update: function() { if (!this._map) { return; } if (!this._container) { this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer()); this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container); this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container); if (this.options.closeButton) { this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper); this._closeButton.innerHTML = '&#215;'; this._closeButton.addEventListener('click', this._onClickClose); } } this._updateContent(); this._updatePosition(); }, _updateContent: function() { if (!this._content || !this._container) { return; } var node = this._wrapper; while (node.hasChildNodes()) { node.removeChild(node.firstChild); } node.appendChild(this._closeButton); node.appendChild(this._content); }, _updatePosition: function() { if (!this._latLng || !this._container) { return; } var pos = this._map.project(this._latLng).round(), anchor = this.options.anchor; if (!anchor) { var width = this._container.offsetWidth, height = this._container.offsetHeight; if (pos.y < height) { anchor = ['top']; } else if (pos.y > this._map.transform.height - height) { anchor = ['bottom']; } else { anchor = []; } if (pos.x < width / 2) { anchor.push('left'); } else if (pos.x > this._map.transform.width - width / 2) { anchor.push('right'); } if (anchor.length === 0) { anchor = 'bottom'; } else { anchor = anchor.join('-'); } this.options.anchor = anchor; } var anchorTranslate = { 'top': 'translate(-50%,0)', 'top-left': 'translate(0,0)', 'top-right': 'translate(-100%,0)', 'bottom': 'translate(-50%,-100%)', 'bottom-left': 'translate(0,-100%)', 'bottom-right': 'translate(-100%,-100%)', 'left': 'translate(0,-50%)', 'right': 'translate(-100%,-50%)' }; var classList = this._container.classList; for (var key in anchorTranslate) { classList.remove('mapboxgl-popup-anchor-' + key); } classList.add('mapboxgl-popup-anchor-' + anchor); DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)'); }, _onClickClose: function() { this.remove(); } }); },{"../geo/lat_lng":18,"../util/dom":88,"../util/evented":90,"../util/util":96}],83:[function(require,module,exports){ 'use strict'; module.exports = Actor; /** * An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model) * that maintains the relationship between asynchronous tasks and the objects * that spin them off - in this case, tasks like parsing parts of styles, * owned by the styles * * @param {WebWorker} target * @param {WebWorker} parent * @private */ function Actor(target, parent) { this.target = target; this.parent = parent; this.callbacks = {}; this.callbackID = 0; this.receive = this.receive.bind(this); this.target.addEventListener('message', this.receive, false); } Actor.prototype.receive = function(message) { var data = message.data, callback; if (data.type === '<response>') { callback = this.callbacks[data.id]; delete this.callbacks[data.id]; callback(data.error || null, data.data); } else if (typeof data.id !== 'undefined') { var id = data.id; this.parent[data.type](data.data, function(err, data, buffers) { this.postMessage({ type: '<response>', id: String(id), error: err ? String(err) : null, data: data }, buffers); }.bind(this)); } else { this.parent[data.type](data.data); } }; Actor.prototype.send = function(type, data, callback, buffers) { var id = null; if (callback) this.callbacks[id = this.callbackID++] = callback; this.postMessage({ type: type, id: String(id), data: data }, buffers); }; /** * Wrapped postMessage API that abstracts around IE's lack of * `transferList` support. * * @param {Object} message * @param {Object} transferList */ Actor.prototype.postMessage = function(message, transferList) { try { this.target.postMessage(message, transferList); } catch (e) { this.target.postMessage(message); // No support for transferList on IE } }; },{}],84:[function(require,module,exports){ 'use strict'; exports.getJSON = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { var data; try { data = JSON.parse(xhr.response); } catch (err) { return callback(err); } callback(null, data); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getArrayBuffer = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { callback(null, xhr.response); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getImage = function(url, callback) { var img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = function() { callback(null, img); }; img.src = url; img.getData = function() { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); return context.getImageData(0, 0, img.width, img.height).data; }; return img; }; exports.getVideo = function(urls, callback) { var video = document.createElement('video'); video.crossOrigin = 'Anonymous'; video.onloadstart = function() { callback(null, video); }; for (var i = 0; i < urls.length; i++) { var s = document.createElement('source'); s.src = urls[i]; video.appendChild(s); } video.getData = function() { return video; }; return video; }; },{}],85:[function(require,module,exports){ 'use strict'; var Canvas = require('./canvas'); var frame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; exports.frame = function(fn) { return frame(fn); }; var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; exports.cancelFrame = function(id) { cancel(id); }; exports.timed = function (fn, dur, ctx) { if (!dur) { fn.call(ctx, 1); return null; } var abort = false, start = window.performance ? window.performance.now() : Date.now(); function tick(now) { if (abort) return; if (!window.performance) now = Date.now(); if (now >= start + dur) { fn.call(ctx, 1); } else { fn.call(ctx, (now - start) / dur); exports.frame(tick); } } exports.frame(tick); return function() { abort = true; }; }; /** * Test whether the basic JavaScript and DOM features required for Mapbox GL are present. * @param {Object} options * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected. * @return {Boolean} Returns true if Mapbox GL should be expected to work, and false if not. */ exports.supported = function(options) { var supports = [ function() { return typeof window !== 'undefined'; }, function() { return typeof document !== 'undefined'; }, function () { return !!(Array.prototype && Array.prototype.every && Array.prototype.filter && Array.prototype.forEach && Array.prototype.indexOf && Array.prototype.lastIndexOf && Array.prototype.map && Array.prototype.some && Array.prototype.reduce && Array.prototype.reduceRight && Array.isArray); }, function() { return !!(Function.prototype && Function.prototype.bind) && !!(Object.keys && Object.create && Object.getPrototypeOf && Object.getOwnPropertyNames && Object.isSealed && Object.isFrozen && Object.isExtensible && Object.getOwnPropertyDescriptor && Object.defineProperty && Object.defineProperties && Object.seal && Object.freeze && Object.preventExtensions); }, function() { return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON; }, function() { return new Canvas().supportsWebGLContext((options && options.failIfMajorPerformanceCaveat) || false); }, function() { return 'Worker' in window; } ]; for (var i = 0; i < supports.length; i++) { if (!supports[i]()) return false; } return true; }; exports.hardwareConcurrency = navigator.hardwareConcurrency || 8; Object.defineProperty(exports, 'devicePixelRatio', { get: function() { return window.devicePixelRatio; } }); },{"./canvas":86}],86:[function(require,module,exports){ 'use strict'; var util = require('../util'); module.exports = Canvas; function Canvas(parent, container) { this.canvas = document.createElement('canvas'); if (parent && container) { this.canvas.style.position = 'absolute'; this.canvas.classList.add('mapboxgl-canvas'); this.canvas.addEventListener('webglcontextlost', parent._contextLost.bind(parent), false); this.canvas.addEventListener('webglcontextrestored', parent._contextRestored.bind(parent), false); this.canvas.setAttribute('tabindex', 0); container.appendChild(this.canvas); } } Canvas.prototype.resize = function(width, height) { var pixelRatio = window.devicePixelRatio || 1; // Request the required canvas size taking the pixelratio into account. this.canvas.width = pixelRatio * width; this.canvas.height = pixelRatio * height; // Maintain the same canvas size, potentially downscaling it for HiDPI displays this.canvas.style.width = width + 'px'; this.canvas.style.height = height + 'px'; }; var requiredContextAttributes = { antialias: false, alpha: true, stencil: true, depth: false }; Canvas.prototype.getWebGLContext = function(attributes) { attributes = util.extend({}, attributes, requiredContextAttributes); return this.canvas.getContext('webgl', attributes) || this.canvas.getContext('experimental-webgl', attributes); }; Canvas.prototype.supportsWebGLContext = function(failIfMajorPerformanceCaveat) { var attributes = util.extend({ failIfMajorPerformanceCaveat: failIfMajorPerformanceCaveat }, requiredContextAttributes); if ('probablySupportsContext' in this.canvas) { return this.canvas.probablySupportsContext('webgl', attributes) || this.canvas.probablySupportsContext('experimental-webgl', attributes); } else if ('supportsContext' in this.canvas) { return this.canvas.supportsContext('webgl', attributes) || this.canvas.supportsContext('experimental-webgl', attributes); } return !!window.WebGLRenderingContext && !!this.getWebGLContext(failIfMajorPerformanceCaveat); }; Canvas.prototype.getElement = function() { return this.canvas; }; },{"../util":96}],87:[function(require,module,exports){ 'use strict'; var Actor = require('../actor'); var WebWorkify = require('webworkify'); module.exports = Dispatcher; function Dispatcher(length, parent) { this.actors = []; this.currentActor = 0; for (var i = 0; i < length; i++) { var worker = new WebWorkify(require('../../source/worker')); var actor = new Actor(worker, parent); actor.name = "Worker " + i; this.actors.push(actor); } } Dispatcher.prototype = { broadcast: function(type, data) { for (var i = 0; i < this.actors.length; i++) { this.actors[i].send(type, data); } }, send: function(type, data, callback, targetID, buffers) { if (typeof targetID !== 'number' || isNaN(targetID)) { // Use round robin to send requests to web workers. targetID = this.currentActor = (this.currentActor + 1) % this.actors.length; } this.actors[targetID].send(type, data, callback, buffers); return targetID; }, remove: function() { for (var i = 0; i < this.actors.length; i++) { this.actors[i].target.terminate(); } this.actors = []; } }; },{"../../source/worker":45,"../actor":83,"webworkify":125}],88:[function(require,module,exports){ 'use strict'; exports.create = function (tagName, className, container) { var el = document.createElement(tagName); if (className) el.className = className; if (container) container.appendChild(el); return el; }; var docStyle = document.documentElement.style; function testProp(props) { for (var i = 0; i < props.length; i++) { if (props[i] in docStyle) { return props[i]; } } } var selectProp = testProp(['userSelect', 'MozUserSelect', 'WebkitUserSelect', 'msUserSelect']), userSelect; exports.disableDrag = function () { if (selectProp) { userSelect = docStyle[selectProp]; docStyle[selectProp] = 'none'; } }; exports.enableDrag = function () { if (selectProp) { docStyle[selectProp] = userSelect; } }; var transformProp = testProp(['transform', 'WebkitTransform']); exports.setTransform = function(el, value) { el.style[transformProp] = value; }; // Suppress the next click, but only if it's immediate. function suppressClick(e) { e.preventDefault(); e.stopPropagation(); window.removeEventListener('click', suppressClick, true); } exports.suppressClick = function() { window.addEventListener('click', suppressClick, true); window.setTimeout(function() { window.removeEventListener('click', suppressClick, true); }, 0); }; },{}],89:[function(require,module,exports){ 'use strict'; module.exports = { HTTP_URL: 'http://a.tiles.mapbox.com', HTTPS_URL: 'https://a.tiles.mapbox.com', FORCE_HTTPS: true, REQUIRE_ACCESS_TOKEN: true }; },{}],90:[function(require,module,exports){ 'use strict'; var util = require('./util'); /** * Methods mixed in to other classes for event capabilities. * @mixin Evented */ var Evented = { /** * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties * * @param {String} type Event type * @param {Function} listener Function to be called when the event is fired */ on: function(type, fn) { this._events = this._events || {}; this._events[type] = this._events[type] || []; this._events[type].push(fn); return this; }, /** * Remove a event listener * * @param {String} [type] Event type. If none is specified, remove all listeners * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed */ off: function(type, fn) { if (!type) { // clear all listeners if no arguments specified delete this._events; return this; } if (!this.listens(type)) return this; if (fn) { var idx = this._events[type].indexOf(fn); if (idx >= 0) { this._events[type].splice(idx, 1); } if (!this._events[type].length) { delete this._events[type]; } } else { delete this._events[type]; } return this; }, /** * Call a function once when an event has fired * * @param {String} type Event type. * @param {Function} listener Function to be called once when the event is fired */ once: function(type, fn) { var wrapper = function(data) { this.off(type, wrapper); fn.call(this, data); }.bind(this); this.on(type, wrapper); return this; }, /** * Fire event of a given string type with the given data object * * @param {String} type The event name * @param {Object} [data] Optional data passed down to the event object * @returns {Boolean} Returns true if the object listens to an event of a particular type */ fire: function(type, data) { if (!this.listens(type)) return this; data = util.extend({}, data); util.extend(data, {type: type, target: this}); // make sure adding/removing listeners inside other listeners won't cause infinite loop var listeners = this._events[type].slice(); for (var i = 0; i < listeners.length; i++) { listeners[i].call(this, data); } return this; }, /** * Check if an event is registered to a type * @returns {Boolean} Returns true if the object listens to an event of a particular type */ listens: function(type) { return !!(this._events && this._events[type]); } }; module.exports = Evented; },{"./util":96}],91:[function(require,module,exports){ 'use strict'; module.exports = Glyphs; function Glyphs(pbf, end) { this.stacks = pbf.readFields(readFontstacks, [], end); } function readFontstacks(tag, stacks, pbf) { if (tag === 1) { var fontstack = pbf.readMessage(readFontstack, {glyphs: {}}); stacks.push(fontstack); } } function readFontstack(tag, fontstack, pbf) { if (tag === 1) fontstack.name = pbf.readString(); else if (tag === 2) fontstack.range = pbf.readString(); else if (tag === 3) { var glyph = pbf.readMessage(readGlyph, {}); fontstack.glyphs[glyph.id] = glyph; } } function readGlyph(tag, glyph, pbf) { if (tag === 1) glyph.id = pbf.readVarint(); else if (tag === 2) glyph.bitmap = pbf.readBytes(); else if (tag === 3) glyph.width = pbf.readVarint(); else if (tag === 4) glyph.height = pbf.readVarint(); else if (tag === 5) glyph.left = pbf.readSVarint(); else if (tag === 6) glyph.top = pbf.readSVarint(); else if (tag === 7) glyph.advance = pbf.readVarint(); } },{}],92:[function(require,module,exports){ 'use strict'; module.exports = interpolate; function interpolate(a, b, t) { return (a * (1 - t)) + (b * t); } interpolate.number = interpolate; interpolate.vec2 = function(from, to, t) { return [ interpolate(from[0], to[0], t), interpolate(from[1], to[1], t) ]; }; /* * Interpolate between two colors given as 4-element arrays. * * @param {Color} from * @param {Color} to * @param {Number} t interpolation factor between 0 and 1 * @returns {Color} interpolated color */ interpolate.color = function(from, to, t) { return [ interpolate(from[0], to[0], t), interpolate(from[1], to[1], t), interpolate(from[2], to[2], t), interpolate(from[3], to[3], t) ]; }; interpolate.array = function(from, to, t) { return from.map(function(d, i) { return interpolate(d, to[i], t); }); }; },{}],93:[function(require,module,exports){ 'use strict'; var config = require('./config'); var browser = require('./browser'); function normalizeURL(url, pathPrefix, accessToken) { accessToken = accessToken || config.ACCESS_TOKEN; if (!accessToken && config.REQUIRE_ACCESS_TOKEN) { throw new Error('An API access token is required to use Mapbox GL. ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } var https = config.FORCE_HTTPS || (typeof document !== 'undefined' && document.location.protocol === 'https:'); url = url.replace(/^mapbox:\/\//, (https ? config.HTTPS_URL : config.HTTP_URL) + pathPrefix); url += url.indexOf('?') !== -1 ? '&access_token=' : '?access_token='; if (config.REQUIRE_ACCESS_TOKEN) { if (accessToken[0] === 's') { throw new Error('Use a public access token (pk.*) with Mapbox GL JS, not a secret access token (sk.*). ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } url += accessToken; } return url; } module.exports.normalizeStyleURL = function(url, accessToken) { var user = url.match(/^mapbox:\/\/([^.]+)/); if (!user) return url; return normalizeURL(url, '/styles/v1/' + user[1] + '/', accessToken); }; module.exports.normalizeSourceURL = function(url, accessToken) { if (!url.match(/^mapbox:\/\//)) return url; url = normalizeURL(url + '.json', '/v4/', accessToken); // TileJSON requests need a secure flag appended to their URLs so // that the server knows to send SSL-ified resource references. if (url.indexOf('https') === 0) url += '&secure'; return url; }; module.exports.normalizeGlyphsURL = function(url, accessToken) { if (!url.match(/^mapbox:\/\//)) return url; return normalizeURL(url, '/v4/', accessToken); }; module.exports.normalizeTileURL = function(url, sourceUrl) { if (!sourceUrl || !sourceUrl.match(/^mapbox:\/\//)) return url; return url.replace(/\.((?:png|jpg)\d*)(?=$|\?)/, browser.devicePixelRatio >= 2 ? '@2x.$1' : '.$1'); }; },{"./browser":85,"./config":89}],94:[function(require,module,exports){ 'use strict'; /* * A [most-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms) * with hash lookup made possible by keeping a list of keys in parallel to * an array of dictionary of values * * @param {number} max number of permitted values * @param {Function} onRemove callback called with items when they expire * @private */ module.exports = MRUCache; function MRUCache(max, onRemove) { this.max = max; this.onRemove = onRemove; this.reset(); } /** * Clear the cache * * @returns {MRUCache} this cache */ MRUCache.prototype.reset = function() { for (var key in this.list) { this.onRemove(this.list[key]); } this.list = {}; this.order = []; return this; }; /* * Add a key, value combination to the cache, trimming its size if this pushes * it over max length. * * @param {string} key lookup key for the item * @param {*} data any value * * @returns {MRUCache} this cache */ MRUCache.prototype.add = function(key, data) { this.list[key] = data; this.order.push(key); if (this.order.length > this.max) { var removedData = this.get(this.order[0]); if (removedData) this.onRemove(removedData); } return this; }; /* * Determine whether the value attached to `key` is present * * @param {string} key the key to be looked-up * @returns {boolean} whether the cache has this value */ MRUCache.prototype.has = function(key) { return key in this.list; }; /* * List all keys in the cache * * @returns {Array<string>} an array of keys in this cache. */ MRUCache.prototype.keys = function() { return this.order; }; /* * Get the value attached to a specific key. If the key is not found, * returns `null` * * @param {string} key the key to look up * @returns {*} the data, or null if it isn't found */ MRUCache.prototype.get = function(key) { if (!this.has(key)) { return null; } var data = this.list[key]; delete this.list[key]; this.order.splice(this.order.indexOf(key), 1); return data; }; },{}],95:[function(require,module,exports){ 'use strict'; module.exports = resolveTokens; /** * Replace tokens in a string template with values in an object * * @param {Object} properties a key/value relationship between tokens and replacements * @param {string} text the template string * @returns {string} the template with tokens replaced * @private */ function resolveTokens(properties, text) { return text.replace(/{([^{}()\[\]<>$=:;.,^]+)}/g, function(match, key) { return key in properties ? properties[key] : ''; }); } },{}],96:[function(require,module,exports){ 'use strict'; var UnitBezier = require('unitbezier'); /** * Given a value `t` that varies between 0 and 1, return * an interpolation function that eases between 0 and 1 in a pleasing * cubic in-out fashion. * * @param {number} t input * @returns {number} input */ exports.easeCubicInOut = function (t) { if (t <= 0) return 0; if (t >= 1) return 1; var t2 = t * t, t3 = t2 * t; return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75); }; /** * Given given (x, y), (x1, y1) control points for a bezier curve, * return a function that interpolates along that curve. * * @param {number} p1x control point 1 x coordinate * @param {number} p1y control point 1 y coordinate * @param {number} p2x control point 2 x coordinate * @param {number} p2y control point 2 y coordinate * @returns {Function} interpolator: receives number value, returns * number value. */ exports.bezier = function(p1x, p1y, p2x, p2y) { var bezier = new UnitBezier(p1x, p1y, p2x, p2y); return function(t) { return bezier.solve(t); }; }; /** * A default bezier-curve powered easing function with * control points (0.25, 0.1) and (0.25, 1) * * @param {number} t * @returns {number} output */ exports.ease = exports.bezier(0.25, 0.1, 0.25, 1); /** * Given a four-element array of numbers that represents a color in * RGBA, return a version for which the RGB components are multiplied * by the A (alpha) component * * @param {Number<Array>} c color array * @returns {Number<Array>} premultiplied color array */ exports.premultiply = function (c) { c[0] *= c[3]; c[1] *= c[3]; c[2] *= c[3]; return c; }; /** * constrain n to the given range via min + max * * @param {Number} n value * @param {Number} min the minimum value to be returned * @param {Number} max the maximum value to be returned * @returns {Number} the clamped value */ exports.clamp = function (n, min, max) { return Math.min(max, Math.max(min, n)); }; /* * constrain n to the given range via modular arithmetic * @param {Number} n * @param {Number} min * @param {Number} max * @returns {Number} constrained number */ exports.wrap = function (n, min, max) { var d = max - min; return n === max ? n : ((n - min) % d + d) % d + min; }; /* * return the first non-null and non-undefined argument to this function. * @returns {*} argument */ exports.coalesce = function() { for (var i = 0; i < arguments.length; i++) { var arg = arguments[i]; if (arg !== null && arg !== undefined) return arg; } }; /* * Call an asynchronous function on an array of arguments, * calling `callback` once all calls complete. * * @param {Array<*>} array input to each call of the async function. * @param {Function} fn an async function with signature (data, callback) * @param {Function} callback a callback run after all async work is done. * called with no arguments * @returns {undefined} */ exports.asyncEach = function (array, fn, callback) { var remaining = array.length; if (remaining === 0) return callback(); function check() { if (--remaining === 0) callback(); } for (var i = 0; i < array.length; i++) fn(array[i], check); }; /* * Compute the difference between the keys in one object and the keys * in another object. * * @param {Object} obj * @param {Object} other * @returns {Array<string>} keys difference */ exports.keysDifference = function (obj, other) { var difference = []; for (var i in obj) { if (!(i in other)) { difference.push(i); } } return difference; }; /** * Given a destination object and optionally many source objects, * copy all properties from the source objects into the destination. * The last source object given overrides properties from previous * source objects. * @param {Object} dest destination object * @param {...Object} sources sources from which properties are pulled * @returns {Object} dest */ exports.extend = function (dest) { for (var i = 1; i < arguments.length; i++) { var src = arguments[i]; for (var k in src) { dest[k] = src[k]; } } return dest; }; /** * Extend a destination object with all properties of the src object, * using defineProperty instead of simple assignment. * @param {Object} dest * @param {Object} src * @returns {Object} dest */ exports.extendAll = function (dest, src) { for (var i in src) { Object.defineProperty(dest, i, Object.getOwnPropertyDescriptor(src, i)); } return dest; }; /** * Extend a parent's prototype with all properties in a properties * object. * * @param {Object} parent * @param {Object} props * @returns {Object} */ exports.inherit = function (parent, props) { var parentProto = typeof parent === 'function' ? parent.prototype : parent, proto = Object.create(parentProto); exports.extendAll(proto, props); return proto; }; /** * Given an object and a number of properties as strings, return version * of that object with only those properties. * * @param {Object} src the object * @param {Array<string>} properties an array of property names chosen * to appear on the resulting object. * @returns {Object} object with limited properties. * @example * var foo = { name: 'Charlie', age: 10 }; * var justName = pick(foo, ['name']); * // justName = { name: 'Charlie' } */ exports.pick = function (src, properties) { var result = {}; for (var i = 0; i < properties.length; i++) { var k = properties[i]; if (k in src) { result[k] = src[k]; } } return result; }; var id = 1; /** * Return a unique numeric id, starting at 1 and incrementing with * each call. * * @returns {Number} unique numeric id. */ exports.uniqueId = function () { return id++; }; /** * Create a version of `fn` that only fires once every `time` millseconds. * * @param {Function} fn the function to be throttled * @param {Number} time millseconds required between function calls * @param {*} context the value of `this` with which the function is called * @returns {Function} debounced function */ exports.throttle = function (fn, time, context) { var lock, args, wrapperFn, later; later = function () { // reset lock and call if queued lock = false; if (args) { wrapperFn.apply(context, args); args = false; } }; wrapperFn = function () { if (lock) { // called too soon, queue to call later args = arguments; } else { // call and lock until later fn.apply(context, arguments); setTimeout(later, time); lock = true; } }; return wrapperFn; }; /** * Create a version of `fn` that is only called `time` milliseconds * after its last invocation * * @param {Function} fn the function to be debounced * @param {Number} time millseconds after which the function will be invoked * @returns {Function} debounced function */ exports.debounce = function(fn, time) { var timer, args; return function() { args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn.apply(null, args); }, time); }; }; /** * Given an array of member function names as strings, replace all of them * with bound versions that will always refer to `context` as `this`. This * is useful for classes where otherwise event bindings would reassign * `this` to the evented object or some other value: this lets you ensure * the `this` value always. * * @param {Array<string>} fns list of member function names * @param {*} context the context value * @returns {undefined} changes functions in-place * @example * function MyClass() { * bindAll(['ontimer'], this); * this.name = 'Tom'; * } * MyClass.prototype.ontimer = function() { * alert(this.name); * }; * var myClass = new MyClass(); * setTimeout(myClass.ontimer, 100); */ exports.bindAll = function(fns, context) { fns.forEach(function(fn) { context[fn] = context[fn].bind(context); }); }; /** * Set the 'options' property on `obj` with properties * from the `options` argument. Properties in the `options` * object will override existing properties. * * @param {Object} obj destination object * @param {Object} options object of override options * @returns {Object} derived options object. */ exports.setOptions = function(obj, options) { if (!obj.hasOwnProperty('options')) { obj.options = obj.options ? Object.create(obj.options) : {}; } for (var i in options) { obj.options[i] = options[i]; } return obj.options; }; },{"unitbezier":116}],97:[function(require,module,exports){ // (c) Dean McNamee <dean@gmail.com>, 2012. // // https://github.com/deanm/css-color-parser-js // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // http://www.w3.org/TR/css3-color/ var kCSSColorTable = { "transparent": [0,0,0,0], "aliceblue": [240,248,255,1], "antiquewhite": [250,235,215,1], "aqua": [0,255,255,1], "aquamarine": [127,255,212,1], "azure": [240,255,255,1], "beige": [245,245,220,1], "bisque": [255,228,196,1], "black": [0,0,0,1], "blanchedalmond": [255,235,205,1], "blue": [0,0,255,1], "blueviolet": [138,43,226,1], "brown": [165,42,42,1], "burlywood": [222,184,135,1], "cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1], "chocolate": [210,105,30,1], "coral": [255,127,80,1], "cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1], "crimson": [220,20,60,1], "cyan": [0,255,255,1], "darkblue": [0,0,139,1], "darkcyan": [0,139,139,1], "darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1], "darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1], "darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1], "darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1], "darkorchid": [153,50,204,1], "darkred": [139,0,0,1], "darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1], "darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1], "darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1], "darkviolet": [148,0,211,1], "deeppink": [255,20,147,1], "deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1], "dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1], "firebrick": [178,34,34,1], "floralwhite": [255,250,240,1], "forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1], "gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1], "gold": [255,215,0,1], "goldenrod": [218,165,32,1], "gray": [128,128,128,1], "green": [0,128,0,1], "greenyellow": [173,255,47,1], "grey": [128,128,128,1], "honeydew": [240,255,240,1], "hotpink": [255,105,180,1], "indianred": [205,92,92,1], "indigo": [75,0,130,1], "ivory": [255,255,240,1], "khaki": [240,230,140,1], "lavender": [230,230,250,1], "lavenderblush": [255,240,245,1], "lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1], "lightblue": [173,216,230,1], "lightcoral": [240,128,128,1], "lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1], "lightgray": [211,211,211,1], "lightgreen": [144,238,144,1], "lightgrey": [211,211,211,1], "lightpink": [255,182,193,1], "lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1], "lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1], "lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1], "lightyellow": [255,255,224,1], "lime": [0,255,0,1], "limegreen": [50,205,50,1], "linen": [250,240,230,1], "magenta": [255,0,255,1], "maroon": [128,0,0,1], "mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1], "mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1], "mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1], "mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1], "mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1], "mintcream": [245,255,250,1], "mistyrose": [255,228,225,1], "moccasin": [255,228,181,1], "navajowhite": [255,222,173,1], "navy": [0,0,128,1], "oldlace": [253,245,230,1], "olive": [128,128,0,1], "olivedrab": [107,142,35,1], "orange": [255,165,0,1], "orangered": [255,69,0,1], "orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1], "palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1], "palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1], "peachpuff": [255,218,185,1], "peru": [205,133,63,1], "pink": [255,192,203,1], "plum": [221,160,221,1], "powderblue": [176,224,230,1], "purple": [128,0,128,1], "red": [255,0,0,1], "rosybrown": [188,143,143,1], "royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1], "salmon": [250,128,114,1], "sandybrown": [244,164,96,1], "seagreen": [46,139,87,1], "seashell": [255,245,238,1], "sienna": [160,82,45,1], "silver": [192,192,192,1], "skyblue": [135,206,235,1], "slateblue": [106,90,205,1], "slategray": [112,128,144,1], "slategrey": [112,128,144,1], "snow": [255,250,250,1], "springgreen": [0,255,127,1], "steelblue": [70,130,180,1], "tan": [210,180,140,1], "teal": [0,128,128,1], "thistle": [216,191,216,1], "tomato": [255,99,71,1], "turquoise": [64,224,208,1], "violet": [238,130,238,1], "wheat": [245,222,179,1], "white": [255,255,255,1], "whitesmoke": [245,245,245,1], "yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]} function clamp_css_byte(i) { // Clamp to integer 0 .. 255. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0. return f < 0 ? 0 : f > 1 ? 1 : f; } function parse_css_int(str) { // int or percentage. if (str[str.length - 1] === '%') return clamp_css_byte(parseFloat(str) / 100 * 255); return clamp_css_byte(parseInt(str)); } function parse_css_float(str) { // float or percentage. if (str[str.length - 1] === '%') return clamp_css_float(parseFloat(str) / 100); return clamp_css_float(parseFloat(str)); } function css_hue_to_rgb(m1, m2, h) { if (h < 0) h += 1; else if (h > 1) h -= 1; if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; return m1; } function parseCSSColor(css_str) { // Remove all whitespace, not compliant, but should just be more accepting. var str = css_str.replace(/ /g, '').toLowerCase(); // Color keywords (and transparent) lookup. if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup. // #abc and #abc123 syntax. if (str[0] === '#') { if (str.length === 4) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN. return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), 1]; } else if (str.length === 7) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN. return [(iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, 1]; } return null; } var op = str.indexOf('('), ep = str.indexOf(')'); if (op !== -1 && ep + 1 === str.length) { var fname = str.substr(0, op); var params = str.substr(op+1, ep-(op+1)).split(','); var alpha = 1; // To allow case fallthrough. switch (fname) { case 'rgba': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'rgb': if (params.length !== 3) return null; return [parse_css_int(params[0]), parse_css_int(params[1]), parse_css_int(params[2]), alpha]; case 'hsla': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'hsl': if (params.length !== 3) return null; var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1 // NOTE(deanm): According to the CSS spec s/l should only be // percentages, but we don't bother and let float or percentage. var s = parse_css_float(params[1]); var l = parse_css_float(params[2]); var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; var m1 = l * 2 - m2; return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255), alpha]; default: return null; } } return null; } try { exports.parseCSSColor = parseCSSColor } catch(e) { } },{}],98:[function(require,module,exports){ 'use strict'; var VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon']; function infix(operator) { return function(_, key, value) { if (key === '$type') { return 't' + operator + VectorTileFeatureTypes.indexOf(value); } else { return 'p[' + JSON.stringify(key) + ']' + operator + JSON.stringify(value); } }; } function strictInfix(operator) { var nonstrictInfix = infix(operator); return function(_, key, value) { if (key === '$type') { return nonstrictInfix(_, key, value); } else { return 'typeof(p[' + JSON.stringify(key) + ']) === typeof(' + JSON.stringify(value) + ') && ' + nonstrictInfix(_, key, value); } }; } var operators = { '==': infix('==='), '!=': infix('!=='), '>': strictInfix('>'), '<': strictInfix('<'), '<=': strictInfix('<='), '>=': strictInfix('>='), 'in': function(_, key) { return Array.prototype.slice.call(arguments, 2).map(function(value) { return '(' + operators['=='](_, key, value) + ')'; }).join('||') || 'false'; }, '!in': function() { return '!(' + operators.in.apply(this, arguments) + ')'; }, 'any': function() { return Array.prototype.slice.call(arguments, 1).map(function(filter) { return '(' + compile(filter) + ')'; }).join('||') || 'false'; }, 'all': function() { return Array.prototype.slice.call(arguments, 1).map(function(filter) { return '(' + compile(filter) + ')'; }).join('&&') || 'true'; }, 'none': function() { return '!(' + operators.any.apply(this, arguments) + ')'; } }; function compile(filter) { return operators[filter[0]].apply(filter, filter); } function truth() { return true; } /** * Given a filter expressed as nested arrays, return a new function * that evaluates whether a given feature (with a .properties or .tags property) * passes its test. * * @param {Array} filter mapbox gl filter * @returns {Function} filter-evaluating function */ module.exports = function (filter) { if (!filter) return truth; var filterStr = 'var p = f.properties || f.tags || {}, t = f.type; return ' + compile(filter) + ';'; // jshint evil: true return new Function('f', filterStr); }; },{}],99:[function(require,module,exports){ 'use strict'; module.exports = clip; /* clip features between two axis-parallel lines: * | | * ___|___ | / * / | \____|____/ * | | */ function clip(features, scale, k1, k2, axis, intersect) { k1 /= scale; k2 /= scale; var clipped = []; for (var i = 0; i < features.length; i++) { var feature = features[i], geometry = feature.geometry, type = feature.type, min, max; if (feature.min) { min = feature.min[axis]; max = feature.max[axis]; if (min >= k1 && max <= k2) { // trivial accept clipped.push(feature); continue; } else if (min > k2 || max < k1) continue; // trivial reject } var slices = type === 1 ? clipPoints(geometry, k1, k2, axis) : clipGeometry(geometry, k1, k2, axis, intersect, type === 3); if (slices.length) { // if a feature got clipped, it will likely get clipped on the next zoom level as well, // so there's no need to recalculate bboxes clipped.push({ geometry: slices, type: type, tags: features[i].tags || null }); } } return clipped.length ? clipped : null; } function clipPoints(geometry, k1, k2, axis) { var slice = []; for (var i = 0; i < geometry.length; i++) { var a = geometry[i], ak = a[axis]; if (ak >= k1 && ak <= k2) slice.push(a); } return slice; } function clipGeometry(geometry, k1, k2, axis, intersect, closed) { var slices = []; for (var i = 0; i < geometry.length; i++) { var ak = 0, bk = 0, b = null, points = geometry[i], area = points.area, dist = points.dist, len = points.length, a, j; var slice = []; for (j = 0; j < len - 1; j++) { a = b || points[j]; b = points[j + 1]; ak = bk || a[axis]; bk = b[axis]; if (ak < k1) { if ((bk > k2)) { // ---|-----|--> slice.push(intersect(a, b, k1), intersect(a, b, k2)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk >= k1) slice.push(intersect(a, b, k1)); // ---|--> | } else if (ak > k2) { if ((bk < k1)) { // <--|-----|--- slice.push(intersect(a, b, k2), intersect(a, b, k1)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk <= k2) slice.push(intersect(a, b, k2)); // | <--|--- } else { slice.push(a); if (bk < k1) { // <--|--- | slice.push(intersect(a, b, k1)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk > k2) { // | ---|--> slice.push(intersect(a, b, k2)); if (!closed) slice = newSlice(slices, slice, area, dist); } // | --> | } } // add the last point a = points[len - 1]; ak = a[axis]; if (ak >= k1 && ak <= k2) slice.push(a); // close the polygon if its endpoints are not the same after clipping if (closed && slice[0] !== slice[slice.length - 1]) slice.push(slice[0]); // add the final slice newSlice(slices, slice, area, dist); } return slices; } function newSlice(slices, slice, area, dist) { if (slice.length) { // we don't recalculate the area/length of the unclipped geometry because the case where it goes // below the visibility threshold as a result of clipping is rare, so we avoid doing unnecessary work slice.area = area; slice.dist = dist; slices.push(slice); } return []; } },{}],100:[function(require,module,exports){ 'use strict'; module.exports = convert; var simplify = require('./simplify'); // converts GeoJSON feature into an intermediate projected JSON vector format with simplification data function convert(data, tolerance) { var features = []; if (data.type === 'FeatureCollection') { for (var i = 0; i < data.features.length; i++) { convertFeature(features, data.features[i], tolerance); } } else if (data.type === 'Feature') { convertFeature(features, data, tolerance); } else { // single geometry or a geometry collection convertFeature(features, {geometry: data}, tolerance); } return features; } function convertFeature(features, feature, tolerance) { var geom = feature.geometry, type = geom.type, coords = geom.coordinates, tags = feature.properties, i, j, rings; if (type === 'Point') { features.push(create(tags, 1, [projectPoint(coords)])); } else if (type === 'MultiPoint') { features.push(create(tags, 1, project(coords))); } else if (type === 'LineString') { features.push(create(tags, 2, [project(coords, tolerance)])); } else if (type === 'MultiLineString' || type === 'Polygon') { rings = []; for (i = 0; i < coords.length; i++) { rings.push(project(coords[i], tolerance)); } features.push(create(tags, type === 'Polygon' ? 3 : 2, rings)); } else if (type === 'MultiPolygon') { rings = []; for (i = 0; i < coords.length; i++) { for (j = 0; j < coords[i].length; j++) { rings.push(project(coords[i][j], tolerance)); } } features.push(create(tags, 3, rings)); } else if (type === 'GeometryCollection') { for (i = 0; i < geom.geometries.length; i++) { convertFeature(features, { geometry: geom.geometries[i], properties: tags }, tolerance); } } else { console.warn('Unsupported GeoJSON type: ' + geom.type); } } function create(tags, type, geometry) { var feature = { geometry: geometry, type: type, tags: tags || null, min: [1, 1], // initial bbox values; max: [0, 0] // note that all coords are in [0..1] range }; calcBBox(feature); return feature; } function project(lonlats, tolerance) { var projected = []; for (var i = 0; i < lonlats.length; i++) { projected.push(projectPoint(lonlats[i])); } if (tolerance) { simplify(projected, tolerance); calcSize(projected); } return projected; } function projectPoint(p) { var sin = Math.sin(p[1] * Math.PI / 180), x = (p[0] / 360 + 0.5), y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI); return [x, y, 0]; } // calculate area and length of the poly function calcSize(points) { var area = 0, dist = 0; for (var i = 0, a, b; i < points.length - 1; i++) { a = b || points[i]; b = points[i + 1]; area += a[0] * b[1] - b[0] * a[1]; // use Manhattan distance instead of Euclidian one to avoid expensive square root computation dist += Math.abs(b[0] - a[0]) + Math.abs(b[1] - a[1]); } points.area = Math.abs(area / 2); points.dist = dist; } // calculate the feature bounding box for faster clipping later function calcBBox(feature) { var geometry = feature.geometry, min = feature.min, max = feature.max; if (feature.type === 1) calcRingBBox(min, max, geometry); else for (var i = 0; i < geometry.length; i++) calcRingBBox(min, max, geometry[i]); return feature; } function calcRingBBox(min, max, points) { for (var i = 0, p; i < points.length; i++) { p = points[i]; min[0] = Math.min(p[0], min[0]); max[0] = Math.max(p[0], max[0]); min[1] = Math.min(p[1], min[1]); max[1] = Math.max(p[1], max[1]); } } },{"./simplify":102}],101:[function(require,module,exports){ 'use strict'; module.exports = geojsonvt; var convert = require('./convert'), // GeoJSON conversion and preprocessing clip = require('./clip'), // stripe clipping algorithm createTile = require('./tile'); // final simplified tile generation function geojsonvt(data, options) { return new GeoJSONVT(data, options); } function GeoJSONVT(data, options) { options = this.options = extend(Object.create(this.options), options); var debug = options.debug; if (debug) console.time('preprocess data'); var z2 = 1 << options.baseZoom, // 2^z features = convert(data, options.tolerance / (z2 * options.extent)); this.tiles = {}; if (debug) { console.timeEnd('preprocess data'); console.time('generate tiles up to z' + options.maxZoom); this.stats = {}; this.total = 0; } // start slicing from the top tile down this.splitTile(features, 0, 0, 0); if (debug) { console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints); console.timeEnd('generate tiles up to z' + options.maxZoom); console.log('tiles generated:', this.total, JSON.stringify(this.stats)); } } GeoJSONVT.prototype.options = { baseZoom: 14, // max zoom to preserve detail on maxZoom: 4, // zoom to slice down to on first pass maxPoints: 100, // stop slicing a tile below this number of points tolerance: 3, // simplification tolerance (higher means simpler) extent: 4096, // tile extent buffer: 64, // tile buffer on each side debug: 0 // logging level (0, 1 or 2) }; GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) { var stack = [features, z, x, y], options = this.options, debug = options.debug, extent = options.extent, buffer = options.buffer; // avoid recursion by using a processing queue while (stack.length) { features = stack.shift(); z = stack.shift(); x = stack.shift(); y = stack.shift(); var z2 = 1 << z, id = toID(z, x, y), tile = this.tiles[id], tileTolerance = z === options.baseZoom ? 0 : options.tolerance / (z2 * extent); if (!tile) { if (debug > 1) console.time('creation'); tile = this.tiles[id] = createTile(features, z2, x, y, tileTolerance, extent, z === options.baseZoom); if (debug) { if (debug > 1) { console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified); console.timeEnd('creation'); } var key = 'z' + z + ':'; this.stats[key] = (this.stats[key] || 0) + 1; this.total++; } } if (!cz && (z === options.maxZoom || tile.numPoints <= options.maxPoints || isClippedSquare(tile.features, extent, buffer)) || z === options.baseZoom || z === cz) { tile.source = features; continue; // stop tiling } if (cz) tile.source = features; else tile.source = null; if (debug > 1) console.time('clipping'); // values we'll use for clipping var k1 = 0.5 * buffer / extent, k2 = 0.5 - k1, k3 = 0.5 + k1, k4 = 1 + k1, tl, bl, tr, br, left, right, m, goLeft, goTop; if (cz) { // if we have a specific tile to drill down to, calculate where to go m = 1 << (cz - z); goLeft = cx / m - x < 0.5; goTop = cy / m - y < 0.5; } tl = bl = tr = br = left = right = null; if (!cz || goLeft) left = clip(features, z2, x - k1, x + k3, 0, intersectX); if (!cz || !goLeft) right = clip(features, z2, x + k2, x + k4, 0, intersectX); if (left) { if (!cz || goTop) tl = clip(left, z2, y - k1, y + k3, 1, intersectY); if (!cz || !goTop) bl = clip(left, z2, y + k2, y + k4, 1, intersectY); } if (right) { if (!cz || goTop) tr = clip(right, z2, y - k1, y + k3, 1, intersectY); if (!cz || !goTop) br = clip(right, z2, y + k2, y + k4, 1, intersectY); } if (debug > 1) console.timeEnd('clipping'); if (tl) stack.push(tl, z + 1, x * 2, y * 2); if (bl) stack.push(bl, z + 1, x * 2, y * 2 + 1); if (tr) stack.push(tr, z + 1, x * 2 + 1, y * 2); if (br) stack.push(br, z + 1, x * 2 + 1, y * 2 + 1); } }; GeoJSONVT.prototype.getTile = function (z, x, y) { var id = toID(z, x, y); if (this.tiles[id]) return this.tiles[id]; var options = this.options, debug = options.debug; if (debug > 1) console.log('drilling down to z%d-%d-%d', z, x, y); var z0 = z, x0 = x, y0 = y, parent; while (!parent && z0 > 0) { z0--; x0 = Math.floor(x0 / 2); y0 = Math.floor(y0 / 2); parent = this.tiles[toID(z0, x0, y0)]; } if (debug > 1) console.log('found parent tile z%d-%d-%d', z0, x0, y0); // if we found a parent tile containing the original geometry, we can drill down from it if (parent.source) { if (isClippedSquare(parent.features, options.extent, options.buffer)) return parent; if (debug) console.time('drilling down'); this.splitTile(parent.source, z0, x0, y0, z, x, y); if (debug) console.timeEnd('drilling down'); } return this.tiles[id]; }; // checks whether a tile is a whole-area fill after clipping; if it is, there's no sense slicing it further function isClippedSquare(features, extent, buffer) { if (features.length !== 1) return false; var feature = features[0]; if (feature.type !== 3 || feature.geometry.length > 1) return false; for (var i = 0; i < feature.geometry[0].length; i++) { var p = feature.geometry[0][i]; if ((p[0] !== -buffer && p[0] !== extent + buffer) || (p[1] !== -buffer && p[1] !== extent + buffer)) return false; } return true; } function toID(z, x, y) { return (((1 << z) * y + x) * 32) + z; } function intersectX(a, b, x) { return [x, (x - a[0]) * (b[1] - a[1]) / (b[0] - a[0]) + a[1], 1]; } function intersectY(a, b, y) { return [(y - a[1]) * (b[0] - a[0]) / (b[1] - a[1]) + a[0], y, 1]; } function extend(dest, src) { for (var i in src) dest[i] = src[i]; return dest; } },{"./clip":99,"./convert":100,"./tile":103}],102:[function(require,module,exports){ 'use strict'; module.exports = simplify; // calculate simplification data using optimized Douglas-Peucker algorithm function simplify(points, tolerance) { var sqTolerance = tolerance * tolerance, len = points.length, first = 0, last = len - 1, stack = [], i, maxSqDist, sqDist, index; // always retain the endpoints (1 is the max value) points[first][2] = 1; points[last][2] = 1; // avoid recursion by using a stack while (last) { maxSqDist = 0; for (i = first + 1; i < last; i++) { sqDist = getSqSegDist(points[i], points[first], points[last]); if (sqDist > maxSqDist) { index = i; maxSqDist = sqDist; } } if (maxSqDist > sqTolerance) { points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate stack.push(first, index, index, last); } last = stack.pop(); first = stack.pop(); } } // square distance from a point to a segment function getSqSegDist(p, a, b) { var x = a[0], y = a[1], bx = b[0], by = b[1], px = p[0], py = p[1], dx = bx - x, dy = by - y; if (dx !== 0 || dy !== 0) { var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy); if (t > 1) { x = bx; y = by; } else if (t > 0) { x += dx * t; y += dy * t; } } dx = px - x; dy = py - y; return dx * dx + dy * dy; } },{}],103:[function(require,module,exports){ 'use strict'; module.exports = createTile; function createTile(features, z2, tx, ty, tolerance, extent, noSimplify) { var tile = { features: [], numPoints: 0, numSimplified: 0, numFeatures: 0, source: null }; for (var i = 0; i < features.length; i++) { tile.numFeatures++; addFeature(tile, features[i], z2, tx, ty, tolerance, extent, noSimplify); } return tile; } function addFeature(tile, feature, z2, tx, ty, tolerance, extent, noSimplify) { var geom = feature.geometry, type = feature.type, transformed = [], sqTolerance = tolerance * tolerance, i, j, ring, p; if (type === 1) { for (i = 0; i < geom.length; i++) { transformed.push(transformPoint(geom[i], z2, tx, ty, extent)); tile.numPoints++; tile.numSimplified++; } } else { // simplify and transform projected coordinates for tile geometry for (i = 0; i < geom.length; i++) { ring = geom[i]; // filter out tiny polylines & polygons if (!noSimplify && ((type === 2 && ring.dist < tolerance) || (type === 3 && ring.area < sqTolerance))) { tile.numPoints += ring.length; continue; } var transformedRing = []; for (j = 0; j < ring.length; j++) { p = ring[j]; // keep points with importance > tolerance if (noSimplify || p[2] > sqTolerance) { transformedRing.push(transformPoint(p, z2, tx, ty, extent)); tile.numSimplified++; } tile.numPoints++; } transformed.push(transformedRing); } } if (transformed.length) { tile.features.push({ geometry: transformed, type: type, tags: feature.tags || null }); } } function transformPoint(p, z2, tx, ty, extent) { var x = Math.round(extent * (p[0] * z2 - tx)), y = Math.round(extent * (p[1] * z2 - ty)); return [x, y]; } },{}],104:[function(require,module,exports){ /** * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV * @version 2.2.1 */ /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function(_global) { "use strict"; var shim = {}; if (typeof(exports) === 'undefined') { if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) { shim.exports = {}; define(function() { return shim.exports; }); } else { // gl-matrix lives in a browser, define its namespaces in global shim.exports = typeof(window) !== 'undefined' ? window : _global; } } else { // gl-matrix lives in commonjs, define its namespaces in exports shim.exports = exports; } (function(exports) { /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ if(!GLMAT_EPSILON) { var GLMAT_EPSILON = 0.000001; } if(!GLMAT_ARRAY_TYPE) { var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array; } if(!GLMAT_RANDOM) { var GLMAT_RANDOM = Math.random; } /** * @class Common utilities * @name glMatrix */ var glMatrix = {}; /** * Sets the type of array used when creating new vectors and matricies * * @param {Type} type Array type, such as Float32Array or Array */ glMatrix.setMatrixArrayType = function(type) { GLMAT_ARRAY_TYPE = type; } if(typeof(exports) !== 'undefined') { exports.glMatrix = glMatrix; } var degree = Math.PI / 180; /** * Convert Degree To Radian * * @param {Number} Angle in Degrees */ glMatrix.toRadian = function(a){ return a * degree; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2 Dimensional Vector * @name vec2 */ var vec2 = {}; /** * Creates a new, empty vec2 * * @returns {vec2} a new 2D vector */ vec2.create = function() { var out = new GLMAT_ARRAY_TYPE(2); out[0] = 0; out[1] = 0; return out; }; /** * Creates a new vec2 initialized with values from an existing vector * * @param {vec2} a vector to clone * @returns {vec2} a new 2D vector */ vec2.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(2); out[0] = a[0]; out[1] = a[1]; return out; }; /** * Creates a new vec2 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @returns {vec2} a new 2D vector */ vec2.fromValues = function(x, y) { var out = new GLMAT_ARRAY_TYPE(2); out[0] = x; out[1] = y; return out; }; /** * Copy the values from one vec2 to another * * @param {vec2} out the receiving vector * @param {vec2} a the source vector * @returns {vec2} out */ vec2.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; return out; }; /** * Set the components of a vec2 to the given values * * @param {vec2} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @returns {vec2} out */ vec2.set = function(out, x, y) { out[0] = x; out[1] = y; return out; }; /** * Adds two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; return out; }; /** * Subtracts vector b from vector a * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; return out; }; /** * Alias for {@link vec2.subtract} * @function */ vec2.sub = vec2.subtract; /** * Multiplies two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; return out; }; /** * Alias for {@link vec2.multiply} * @function */ vec2.mul = vec2.multiply; /** * Divides two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; return out; }; /** * Alias for {@link vec2.divide} * @function */ vec2.div = vec2.divide; /** * Returns the minimum of two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); return out; }; /** * Returns the maximum of two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); return out; }; /** * Scales a vec2 by a scalar number * * @param {vec2} out the receiving vector * @param {vec2} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec2} out */ vec2.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; return out; }; /** * Adds two vec2's after scaling the second operand by a scalar value * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec2} out */ vec2.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); return out; }; /** * Calculates the euclidian distance between two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} distance between a and b */ vec2.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1]; return Math.sqrt(x*x + y*y); }; /** * Alias for {@link vec2.distance} * @function */ vec2.dist = vec2.distance; /** * Calculates the squared euclidian distance between two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} squared distance between a and b */ vec2.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1]; return x*x + y*y; }; /** * Alias for {@link vec2.squaredDistance} * @function */ vec2.sqrDist = vec2.squaredDistance; /** * Calculates the length of a vec2 * * @param {vec2} a vector to calculate length of * @returns {Number} length of a */ vec2.length = function (a) { var x = a[0], y = a[1]; return Math.sqrt(x*x + y*y); }; /** * Alias for {@link vec2.length} * @function */ vec2.len = vec2.length; /** * Calculates the squared length of a vec2 * * @param {vec2} a vector to calculate squared length of * @returns {Number} squared length of a */ vec2.squaredLength = function (a) { var x = a[0], y = a[1]; return x*x + y*y; }; /** * Alias for {@link vec2.squaredLength} * @function */ vec2.sqrLen = vec2.squaredLength; /** * Negates the components of a vec2 * * @param {vec2} out the receiving vector * @param {vec2} a vector to negate * @returns {vec2} out */ vec2.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; return out; }; /** * Normalize a vec2 * * @param {vec2} out the receiving vector * @param {vec2} a vector to normalize * @returns {vec2} out */ vec2.normalize = function(out, a) { var x = a[0], y = a[1]; var len = x*x + y*y; if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; } return out; }; /** * Calculates the dot product of two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} dot product of a and b */ vec2.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1]; }; /** * Computes the cross product of two vec2's * Note that the cross product must by definition produce a 3D vector * * @param {vec3} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec3} out */ vec2.cross = function(out, a, b) { var z = a[0] * b[1] - a[1] * b[0]; out[0] = out[1] = 0; out[2] = z; return out; }; /** * Performs a linear interpolation between two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec2} out */ vec2.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); return out; }; /** * Generates a random vector with the given scale * * @param {vec2} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec2} out */ vec2.random = function (out, scale) { scale = scale || 1.0; var r = GLMAT_RANDOM() * 2.0 * Math.PI; out[0] = Math.cos(r) * scale; out[1] = Math.sin(r) * scale; return out; }; /** * Transforms the vec2 with a mat2 * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat2} m matrix to transform with * @returns {vec2} out */ vec2.transformMat2 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[2] * y; out[1] = m[1] * x + m[3] * y; return out; }; /** * Transforms the vec2 with a mat2d * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat2d} m matrix to transform with * @returns {vec2} out */ vec2.transformMat2d = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[2] * y + m[4]; out[1] = m[1] * x + m[3] * y + m[5]; return out; }; /** * Transforms the vec2 with a mat3 * 3rd vector component is implicitly '1' * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat3} m matrix to transform with * @returns {vec2} out */ vec2.transformMat3 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[3] * y + m[6]; out[1] = m[1] * x + m[4] * y + m[7]; return out; }; /** * Transforms the vec2 with a mat4 * 3rd vector component is implicitly '0' * 4th vector component is implicitly '1' * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec2} out */ vec2.transformMat4 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[4] * y + m[12]; out[1] = m[1] * x + m[5] * y + m[13]; return out; }; /** * Perform some operation over an array of vec2s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec2.forEach = (function() { var vec = vec2.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 2; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec2} vec vector to represent as a string * @returns {String} string representation of the vector */ vec2.str = function (a) { return 'vec2(' + a[0] + ', ' + a[1] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec2 = vec2; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 3 Dimensional Vector * @name vec3 */ var vec3 = {}; /** * Creates a new, empty vec3 * * @returns {vec3} a new 3D vector */ vec3.create = function() { var out = new GLMAT_ARRAY_TYPE(3); out[0] = 0; out[1] = 0; out[2] = 0; return out; }; /** * Creates a new vec3 initialized with values from an existing vector * * @param {vec3} a vector to clone * @returns {vec3} a new 3D vector */ vec3.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(3); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; }; /** * Creates a new vec3 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} a new 3D vector */ vec3.fromValues = function(x, y, z) { var out = new GLMAT_ARRAY_TYPE(3); out[0] = x; out[1] = y; out[2] = z; return out; }; /** * Copy the values from one vec3 to another * * @param {vec3} out the receiving vector * @param {vec3} a the source vector * @returns {vec3} out */ vec3.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; }; /** * Set the components of a vec3 to the given values * * @param {vec3} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} out */ vec3.set = function(out, x, y, z) { out[0] = x; out[1] = y; out[2] = z; return out; }; /** * Adds two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; return out; }; /** * Subtracts vector b from vector a * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; return out; }; /** * Alias for {@link vec3.subtract} * @function */ vec3.sub = vec3.subtract; /** * Multiplies two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; out[2] = a[2] * b[2]; return out; }; /** * Alias for {@link vec3.multiply} * @function */ vec3.mul = vec3.multiply; /** * Divides two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; out[2] = a[2] / b[2]; return out; }; /** * Alias for {@link vec3.divide} * @function */ vec3.div = vec3.divide; /** * Returns the minimum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); out[2] = Math.min(a[2], b[2]); return out; }; /** * Returns the maximum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); out[2] = Math.max(a[2], b[2]); return out; }; /** * Scales a vec3 by a scalar number * * @param {vec3} out the receiving vector * @param {vec3} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec3} out */ vec3.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; return out; }; /** * Adds two vec3's after scaling the second operand by a scalar value * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec3} out */ vec3.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); out[2] = a[2] + (b[2] * scale); return out; }; /** * Calculates the euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} distance between a and b */ vec3.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2]; return Math.sqrt(x*x + y*y + z*z); }; /** * Alias for {@link vec3.distance} * @function */ vec3.dist = vec3.distance; /** * Calculates the squared euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} squared distance between a and b */ vec3.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2]; return x*x + y*y + z*z; }; /** * Alias for {@link vec3.squaredDistance} * @function */ vec3.sqrDist = vec3.squaredDistance; /** * Calculates the length of a vec3 * * @param {vec3} a vector to calculate length of * @returns {Number} length of a */ vec3.length = function (a) { var x = a[0], y = a[1], z = a[2]; return Math.sqrt(x*x + y*y + z*z); }; /** * Alias for {@link vec3.length} * @function */ vec3.len = vec3.length; /** * Calculates the squared length of a vec3 * * @param {vec3} a vector to calculate squared length of * @returns {Number} squared length of a */ vec3.squaredLength = function (a) { var x = a[0], y = a[1], z = a[2]; return x*x + y*y + z*z; }; /** * Alias for {@link vec3.squaredLength} * @function */ vec3.sqrLen = vec3.squaredLength; /** * Negates the components of a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to negate * @returns {vec3} out */ vec3.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; return out; }; /** * Normalize a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to normalize * @returns {vec3} out */ vec3.normalize = function(out, a) { var x = a[0], y = a[1], z = a[2]; var len = x*x + y*y + z*z; if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; out[2] = a[2] * len; } return out; }; /** * Calculates the dot product of two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} dot product of a and b */ vec3.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }; /** * Computes the cross product of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.cross = function(out, a, b) { var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2]; out[0] = ay * bz - az * by; out[1] = az * bx - ax * bz; out[2] = ax * by - ay * bx; return out; }; /** * Performs a linear interpolation between two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec3} out */ vec3.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1], az = a[2]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); return out; }; /** * Generates a random vector with the given scale * * @param {vec3} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec3} out */ vec3.random = function (out, scale) { scale = scale || 1.0; var r = GLMAT_RANDOM() * 2.0 * Math.PI; var z = (GLMAT_RANDOM() * 2.0) - 1.0; var zScale = Math.sqrt(1.0-z*z) * scale; out[0] = Math.cos(r) * zScale; out[1] = Math.sin(r) * zScale; out[2] = z * scale; return out; }; /** * Transforms the vec3 with a mat4. * 4th vector component is implicitly '1' * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec3} out */ vec3.transformMat4 = function(out, a, m) { var x = a[0], y = a[1], z = a[2]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; return out; }; /** * Transforms the vec3 with a mat3. * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m the 3x3 matrix to transform with * @returns {vec3} out */ vec3.transformMat3 = function(out, a, m) { var x = a[0], y = a[1], z = a[2]; out[0] = x * m[0] + y * m[3] + z * m[6]; out[1] = x * m[1] + y * m[4] + z * m[7]; out[2] = x * m[2] + y * m[5] + z * m[8]; return out; }; /** * Transforms the vec3 with a quat * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {quat} q quaternion to transform with * @returns {vec3} out */ vec3.transformQuat = function(out, a, q) { // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations var x = a[0], y = a[1], z = a[2], qx = q[0], qy = q[1], qz = q[2], qw = q[3], // calculate quat * vec ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; return out; }; /* * Rotate a 3D vector around the x-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateX = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[0]; r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c); r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c); //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /* * Rotate a 3D vector around the y-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateY = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c); r[1] = p[1]; r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c); //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /* * Rotate a 3D vector around the z-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateZ = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c); r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c); r[2] = p[2]; //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /** * Perform some operation over an array of vec3s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec3.forEach = (function() { var vec = vec3.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 3; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec3} vec vector to represent as a string * @returns {String} string representation of the vector */ vec3.str = function (a) { return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec3 = vec3; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 4 Dimensional Vector * @name vec4 */ var vec4 = {}; /** * Creates a new, empty vec4 * * @returns {vec4} a new 4D vector */ vec4.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; return out; }; /** * Creates a new vec4 initialized with values from an existing vector * * @param {vec4} a vector to clone * @returns {vec4} a new 4D vector */ vec4.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Creates a new vec4 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {vec4} a new 4D vector */ vec4.fromValues = function(x, y, z, w) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out; }; /** * Copy the values from one vec4 to another * * @param {vec4} out the receiving vector * @param {vec4} a the source vector * @returns {vec4} out */ vec4.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Set the components of a vec4 to the given values * * @param {vec4} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {vec4} out */ vec4.set = function(out, x, y, z, w) { out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out; }; /** * Adds two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; return out; }; /** * Subtracts vector b from vector a * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; out[3] = a[3] - b[3]; return out; }; /** * Alias for {@link vec4.subtract} * @function */ vec4.sub = vec4.subtract; /** * Multiplies two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; out[2] = a[2] * b[2]; out[3] = a[3] * b[3]; return out; }; /** * Alias for {@link vec4.multiply} * @function */ vec4.mul = vec4.multiply; /** * Divides two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; out[2] = a[2] / b[2]; out[3] = a[3] / b[3]; return out; }; /** * Alias for {@link vec4.divide} * @function */ vec4.div = vec4.divide; /** * Returns the minimum of two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); out[2] = Math.min(a[2], b[2]); out[3] = Math.min(a[3], b[3]); return out; }; /** * Returns the maximum of two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); out[2] = Math.max(a[2], b[2]); out[3] = Math.max(a[3], b[3]); return out; }; /** * Scales a vec4 by a scalar number * * @param {vec4} out the receiving vector * @param {vec4} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec4} out */ vec4.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; return out; }; /** * Adds two vec4's after scaling the second operand by a scalar value * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec4} out */ vec4.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); out[2] = a[2] + (b[2] * scale); out[3] = a[3] + (b[3] * scale); return out; }; /** * Calculates the euclidian distance between two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} distance between a and b */ vec4.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3]; return Math.sqrt(x*x + y*y + z*z + w*w); }; /** * Alias for {@link vec4.distance} * @function */ vec4.dist = vec4.distance; /** * Calculates the squared euclidian distance between two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} squared distance between a and b */ vec4.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3]; return x*x + y*y + z*z + w*w; }; /** * Alias for {@link vec4.squaredDistance} * @function */ vec4.sqrDist = vec4.squaredDistance; /** * Calculates the length of a vec4 * * @param {vec4} a vector to calculate length of * @returns {Number} length of a */ vec4.length = function (a) { var x = a[0], y = a[1], z = a[2], w = a[3]; return Math.sqrt(x*x + y*y + z*z + w*w); }; /** * Alias for {@link vec4.length} * @function */ vec4.len = vec4.length; /** * Calculates the squared length of a vec4 * * @param {vec4} a vector to calculate squared length of * @returns {Number} squared length of a */ vec4.squaredLength = function (a) { var x = a[0], y = a[1], z = a[2], w = a[3]; return x*x + y*y + z*z + w*w; }; /** * Alias for {@link vec4.squaredLength} * @function */ vec4.sqrLen = vec4.squaredLength; /** * Negates the components of a vec4 * * @param {vec4} out the receiving vector * @param {vec4} a vector to negate * @returns {vec4} out */ vec4.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = -a[3]; return out; }; /** * Normalize a vec4 * * @param {vec4} out the receiving vector * @param {vec4} a vector to normalize * @returns {vec4} out */ vec4.normalize = function(out, a) { var x = a[0], y = a[1], z = a[2], w = a[3]; var len = x*x + y*y + z*z + w*w; if (len > 0) { len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; out[2] = a[2] * len; out[3] = a[3] * len; } return out; }; /** * Calculates the dot product of two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} dot product of a and b */ vec4.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; }; /** * Performs a linear interpolation between two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec4} out */ vec4.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1], az = a[2], aw = a[3]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); out[3] = aw + t * (b[3] - aw); return out; }; /** * Generates a random vector with the given scale * * @param {vec4} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec4} out */ vec4.random = function (out, scale) { scale = scale || 1.0; //TODO: This is a pretty awful way of doing this. Find something better. out[0] = GLMAT_RANDOM(); out[1] = GLMAT_RANDOM(); out[2] = GLMAT_RANDOM(); out[3] = GLMAT_RANDOM(); vec4.normalize(out, out); vec4.scale(out, out, scale); return out; }; /** * Transforms the vec4 with a mat4. * * @param {vec4} out the receiving vector * @param {vec4} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec4} out */ vec4.transformMat4 = function(out, a, m) { var x = a[0], y = a[1], z = a[2], w = a[3]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; return out; }; /** * Transforms the vec4 with a quat * * @param {vec4} out the receiving vector * @param {vec4} a the vector to transform * @param {quat} q quaternion to transform with * @returns {vec4} out */ vec4.transformQuat = function(out, a, q) { var x = a[0], y = a[1], z = a[2], qx = q[0], qy = q[1], qz = q[2], qw = q[3], // calculate quat * vec ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; return out; }; /** * Perform some operation over an array of vec4s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec4.forEach = (function() { var vec = vec4.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 4; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec4} vec vector to represent as a string * @returns {String} string representation of the vector */ vec4.str = function (a) { return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec4 = vec4; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2x2 Matrix * @name mat2 */ var mat2 = {}; /** * Creates a new identity mat2 * * @returns {mat2} a new 2x2 matrix */ mat2.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Creates a new mat2 initialized with values from an existing matrix * * @param {mat2} a matrix to clone * @returns {mat2} a new 2x2 matrix */ mat2.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Copy the values from one mat2 to another * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Set a mat2 to the identity matrix * * @param {mat2} out the receiving matrix * @returns {mat2} out */ mat2.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Transpose the values of a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a1 = a[1]; out[1] = a[2]; out[2] = a1; } else { out[0] = a[0]; out[1] = a[2]; out[2] = a[1]; out[3] = a[3]; } return out; }; /** * Inverts a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.invert = function(out, a) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], // Calculate the determinant det = a0 * a3 - a2 * a1; if (!det) { return null; } det = 1.0 / det; out[0] = a3 * det; out[1] = -a1 * det; out[2] = -a2 * det; out[3] = a0 * det; return out; }; /** * Calculates the adjugate of a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.adjoint = function(out, a) { // Caching this value is nessecary if out == a var a0 = a[0]; out[0] = a[3]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a0; return out; }; /** * Calculates the determinant of a mat2 * * @param {mat2} a the source matrix * @returns {Number} determinant of a */ mat2.determinant = function (a) { return a[0] * a[3] - a[2] * a[1]; }; /** * Multiplies two mat2's * * @param {mat2} out the receiving matrix * @param {mat2} a the first operand * @param {mat2} b the second operand * @returns {mat2} out */ mat2.multiply = function (out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; return out; }; /** * Alias for {@link mat2.multiply} * @function */ mat2.mul = mat2.multiply; /** * Rotates a mat2 by the given angle * * @param {mat2} out the receiving matrix * @param {mat2} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2} out */ mat2.rotate = function (out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], s = Math.sin(rad), c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; return out; }; /** * Scales the mat2 by the dimensions in the given vec2 * * @param {mat2} out the receiving matrix * @param {mat2} a the matrix to rotate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat2} out **/ mat2.scale = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; return out; }; /** * Returns a string representation of a mat2 * * @param {mat2} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat2.str = function (a) { return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; /** * Returns Frobenius norm of a mat2 * * @param {mat2} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat2.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2))) }; /** * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix * @param {mat2} L the lower triangular matrix * @param {mat2} D the diagonal matrix * @param {mat2} U the upper triangular matrix * @param {mat2} a the input matrix to factorize */ mat2.LDU = function (L, D, U, a) { L[2] = a[2]/a[0]; U[0] = a[0]; U[1] = a[1]; U[3] = a[3] - L[2] * U[1]; return [L, D, U]; }; if(typeof(exports) !== 'undefined') { exports.mat2 = mat2; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2x3 Matrix * @name mat2d * * @description * A mat2d contains six elements defined as: * <pre> * [a, c, tx, * b, d, ty] * </pre> * This is a short form for the 3x3 matrix: * <pre> * [a, c, tx, * b, d, ty, * 0, 0, 1] * </pre> * The last row is ignored so the array is shorter and operations are faster. */ var mat2d = {}; /** * Creates a new identity mat2d * * @returns {mat2d} a new 2x3 matrix */ mat2d.create = function() { var out = new GLMAT_ARRAY_TYPE(6); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out; }; /** * Creates a new mat2d initialized with values from an existing matrix * * @param {mat2d} a matrix to clone * @returns {mat2d} a new 2x3 matrix */ mat2d.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(6); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; }; /** * Copy the values from one mat2d to another * * @param {mat2d} out the receiving matrix * @param {mat2d} a the source matrix * @returns {mat2d} out */ mat2d.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; }; /** * Set a mat2d to the identity matrix * * @param {mat2d} out the receiving matrix * @returns {mat2d} out */ mat2d.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out; }; /** * Inverts a mat2d * * @param {mat2d} out the receiving matrix * @param {mat2d} a the source matrix * @returns {mat2d} out */ mat2d.invert = function(out, a) { var aa = a[0], ab = a[1], ac = a[2], ad = a[3], atx = a[4], aty = a[5]; var det = aa * ad - ab * ac; if(!det){ return null; } det = 1.0 / det; out[0] = ad * det; out[1] = -ab * det; out[2] = -ac * det; out[3] = aa * det; out[4] = (ac * aty - ad * atx) * det; out[5] = (ab * atx - aa * aty) * det; return out; }; /** * Calculates the determinant of a mat2d * * @param {mat2d} a the source matrix * @returns {Number} determinant of a */ mat2d.determinant = function (a) { return a[0] * a[3] - a[1] * a[2]; }; /** * Multiplies two mat2d's * * @param {mat2d} out the receiving matrix * @param {mat2d} a the first operand * @param {mat2d} b the second operand * @returns {mat2d} out */ mat2d.multiply = function (out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; out[4] = a0 * b4 + a2 * b5 + a4; out[5] = a1 * b4 + a3 * b5 + a5; return out; }; /** * Alias for {@link mat2d.multiply} * @function */ mat2d.mul = mat2d.multiply; /** * Rotates a mat2d by the given angle * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2d} out */ mat2d.rotate = function (out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], s = Math.sin(rad), c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; out[4] = a4; out[5] = a5; return out; }; /** * Scales the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to translate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat2d} out **/ mat2d.scale = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; out[4] = a4; out[5] = a5; return out; }; /** * Translates the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to translate * @param {vec2} v the vec2 to translate the matrix by * @returns {mat2d} out **/ mat2d.translate = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], v0 = v[0], v1 = v[1]; out[0] = a0; out[1] = a1; out[2] = a2; out[3] = a3; out[4] = a0 * v0 + a2 * v1 + a4; out[5] = a1 * v0 + a3 * v1 + a5; return out; }; /** * Returns a string representation of a mat2d * * @param {mat2d} a matrix to represent as a string * @returns {String} string representation of the matrix */ mat2d.str = function (a) { return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ')'; }; /** * Returns Frobenius norm of a mat2d * * @param {mat2d} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat2d.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1)) }; if(typeof(exports) !== 'undefined') { exports.mat2d = mat2d; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 3x3 Matrix * @name mat3 */ var mat3 = {}; /** * Creates a new identity mat3 * * @returns {mat3} a new 3x3 matrix */ mat3.create = function() { var out = new GLMAT_ARRAY_TYPE(9); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 1; out[5] = 0; out[6] = 0; out[7] = 0; out[8] = 1; return out; }; /** * Copies the upper-left 3x3 values into the given mat3. * * @param {mat3} out the receiving 3x3 matrix * @param {mat4} a the source 4x4 matrix * @returns {mat3} out */ mat3.fromMat4 = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[4]; out[4] = a[5]; out[5] = a[6]; out[6] = a[8]; out[7] = a[9]; out[8] = a[10]; return out; }; /** * Creates a new mat3 initialized with values from an existing matrix * * @param {mat3} a matrix to clone * @returns {mat3} a new 3x3 matrix */ mat3.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(9); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Copy the values from one mat3 to another * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Set a mat3 to the identity matrix * * @param {mat3} out the receiving matrix * @returns {mat3} out */ mat3.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 1; out[5] = 0; out[6] = 0; out[7] = 0; out[8] = 1; return out; }; /** * Transpose the values of a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a01 = a[1], a02 = a[2], a12 = a[5]; out[1] = a[3]; out[2] = a[6]; out[3] = a01; out[5] = a[7]; out[6] = a02; out[7] = a12; } else { out[0] = a[0]; out[1] = a[3]; out[2] = a[6]; out[3] = a[1]; out[4] = a[4]; out[5] = a[7]; out[6] = a[2]; out[7] = a[5]; out[8] = a[8]; } return out; }; /** * Inverts a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.invert = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], b01 = a22 * a11 - a12 * a21, b11 = -a22 * a10 + a12 * a20, b21 = a21 * a10 - a11 * a20, // Calculate the determinant det = a00 * b01 + a01 * b11 + a02 * b21; if (!det) { return null; } det = 1.0 / det; out[0] = b01 * det; out[1] = (-a22 * a01 + a02 * a21) * det; out[2] = (a12 * a01 - a02 * a11) * det; out[3] = b11 * det; out[4] = (a22 * a00 - a02 * a20) * det; out[5] = (-a12 * a00 + a02 * a10) * det; out[6] = b21 * det; out[7] = (-a21 * a00 + a01 * a20) * det; out[8] = (a11 * a00 - a01 * a10) * det; return out; }; /** * Calculates the adjugate of a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.adjoint = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8]; out[0] = (a11 * a22 - a12 * a21); out[1] = (a02 * a21 - a01 * a22); out[2] = (a01 * a12 - a02 * a11); out[3] = (a12 * a20 - a10 * a22); out[4] = (a00 * a22 - a02 * a20); out[5] = (a02 * a10 - a00 * a12); out[6] = (a10 * a21 - a11 * a20); out[7] = (a01 * a20 - a00 * a21); out[8] = (a00 * a11 - a01 * a10); return out; }; /** * Calculates the determinant of a mat3 * * @param {mat3} a the source matrix * @returns {Number} determinant of a */ mat3.determinant = function (a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8]; return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); }; /** * Multiplies two mat3's * * @param {mat3} out the receiving matrix * @param {mat3} a the first operand * @param {mat3} b the second operand * @returns {mat3} out */ mat3.multiply = function (out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], b00 = b[0], b01 = b[1], b02 = b[2], b10 = b[3], b11 = b[4], b12 = b[5], b20 = b[6], b21 = b[7], b22 = b[8]; out[0] = b00 * a00 + b01 * a10 + b02 * a20; out[1] = b00 * a01 + b01 * a11 + b02 * a21; out[2] = b00 * a02 + b01 * a12 + b02 * a22; out[3] = b10 * a00 + b11 * a10 + b12 * a20; out[4] = b10 * a01 + b11 * a11 + b12 * a21; out[5] = b10 * a02 + b11 * a12 + b12 * a22; out[6] = b20 * a00 + b21 * a10 + b22 * a20; out[7] = b20 * a01 + b21 * a11 + b22 * a21; out[8] = b20 * a02 + b21 * a12 + b22 * a22; return out; }; /** * Alias for {@link mat3.multiply} * @function */ mat3.mul = mat3.multiply; /** * Translate a mat3 by the given vector * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to translate * @param {vec2} v vector to translate by * @returns {mat3} out */ mat3.translate = function(out, a, v) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], x = v[0], y = v[1]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a10; out[4] = a11; out[5] = a12; out[6] = x * a00 + y * a10 + a20; out[7] = x * a01 + y * a11 + a21; out[8] = x * a02 + y * a12 + a22; return out; }; /** * Rotates a mat3 by the given angle * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat3} out */ mat3.rotate = function (out, a, rad) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], s = Math.sin(rad), c = Math.cos(rad); out[0] = c * a00 + s * a10; out[1] = c * a01 + s * a11; out[2] = c * a02 + s * a12; out[3] = c * a10 - s * a00; out[4] = c * a11 - s * a01; out[5] = c * a12 - s * a02; out[6] = a20; out[7] = a21; out[8] = a22; return out; }; /** * Scales the mat3 by the dimensions in the given vec2 * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to rotate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat3} out **/ mat3.scale = function(out, a, v) { var x = v[0], y = v[1]; out[0] = x * a[0]; out[1] = x * a[1]; out[2] = x * a[2]; out[3] = y * a[3]; out[4] = y * a[4]; out[5] = y * a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Copies the values from a mat2d into a mat3 * * @param {mat3} out the receiving matrix * @param {mat2d} a the matrix to copy * @returns {mat3} out **/ mat3.fromMat2d = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = 0; out[3] = a[2]; out[4] = a[3]; out[5] = 0; out[6] = a[4]; out[7] = a[5]; out[8] = 1; return out; }; /** * Calculates a 3x3 matrix from the given quaternion * * @param {mat3} out mat3 receiving operation result * @param {quat} q Quaternion to create matrix from * * @returns {mat3} out */ mat3.fromQuat = function (out, q) { var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - yy - zz; out[3] = yx - wz; out[6] = zx + wy; out[1] = yx + wz; out[4] = 1 - xx - zz; out[7] = zy - wx; out[2] = zx - wy; out[5] = zy + wx; out[8] = 1 - xx - yy; return out; }; /** * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix * * @param {mat3} out mat3 receiving operation result * @param {mat4} a Mat4 to derive the normal matrix from * * @returns {mat3} out */ mat3.normalFromMat4 = function (out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, // Calculate the determinant det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det; return out; }; /** * Returns a string representation of a mat3 * * @param {mat3} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat3.str = function (a) { return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')'; }; /** * Returns Frobenius norm of a mat3 * * @param {mat3} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat3.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2))) }; if(typeof(exports) !== 'undefined') { exports.mat3 = mat3; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 4x4 Matrix * @name mat4 */ var mat4 = {}; /** * Creates a new identity mat4 * * @returns {mat4} a new 4x4 matrix */ mat4.create = function() { var out = new GLMAT_ARRAY_TYPE(16); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Creates a new mat4 initialized with values from an existing matrix * * @param {mat4} a matrix to clone * @returns {mat4} a new 4x4 matrix */ mat4.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(16); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Copy the values from one mat4 to another * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Set a mat4 to the identity matrix * * @param {mat4} out the receiving matrix * @returns {mat4} out */ mat4.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Transpose the values of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a01 = a[1], a02 = a[2], a03 = a[3], a12 = a[6], a13 = a[7], a23 = a[11]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a01; out[6] = a[9]; out[7] = a[13]; out[8] = a02; out[9] = a12; out[11] = a[14]; out[12] = a03; out[13] = a13; out[14] = a23; } else { out[0] = a[0]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a[1]; out[5] = a[5]; out[6] = a[9]; out[7] = a[13]; out[8] = a[2]; out[9] = a[6]; out[10] = a[10]; out[11] = a[14]; out[12] = a[3]; out[13] = a[7]; out[14] = a[11]; out[15] = a[15]; } return out; }; /** * Inverts a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.invert = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, // Calculate the determinant det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; }; /** * Calculates the adjugate of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.adjoint = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); return out; }; /** * Calculates the determinant of a mat4 * * @param {mat4} a the source matrix * @returns {Number} determinant of a */ mat4.determinant = function (a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32; // Calculate the determinant return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; }; /** * Multiplies two mat4's * * @param {mat4} out the receiving matrix * @param {mat4} a the first operand * @param {mat4} b the second operand * @returns {mat4} out */ mat4.multiply = function (out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; // Cache only the current line of the second matrix var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; return out; }; /** * Alias for {@link mat4.multiply} * @function */ mat4.mul = mat4.multiply; /** * Translate a mat4 by the given vector * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to translate * @param {vec3} v vector to translate by * @returns {mat4} out */ mat4.translate = function (out, a, v) { var x = v[0], y = v[1], z = v[2], a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23; if (a === out) { out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; } else { a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; out[12] = a00 * x + a10 * y + a20 * z + a[12]; out[13] = a01 * x + a11 * y + a21 * z + a[13]; out[14] = a02 * x + a12 * y + a22 * z + a[14]; out[15] = a03 * x + a13 * y + a23 * z + a[15]; } return out; }; /** * Scales the mat4 by the dimensions in the given vec3 * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to scale * @param {vec3} v the vec3 to scale the matrix by * @returns {mat4} out **/ mat4.scale = function(out, a, v) { var x = v[0], y = v[1], z = v[2]; out[0] = a[0] * x; out[1] = a[1] * x; out[2] = a[2] * x; out[3] = a[3] * x; out[4] = a[4] * y; out[5] = a[5] * y; out[6] = a[6] * y; out[7] = a[7] * y; out[8] = a[8] * z; out[9] = a[9] * z; out[10] = a[10] * z; out[11] = a[11] * z; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Rotates a mat4 by the given angle * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @param {vec3} axis the axis to rotate around * @returns {mat4} out */ mat4.rotate = function (out, a, rad, axis) { var x = axis[0], y = axis[1], z = axis[2], len = Math.sqrt(x * x + y * y + z * z), s, c, t, a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20, b21, b22; if (Math.abs(len) < GLMAT_EPSILON) { return null; } len = 1 / len; x *= len; y *= len; z *= len; s = Math.sin(rad); c = Math.cos(rad); t = 1 - c; a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; // Construct the elements of the rotation matrix b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; // Perform rotation-specific matrix multiplication out[0] = a00 * b00 + a10 * b01 + a20 * b02; out[1] = a01 * b00 + a11 * b01 + a21 * b02; out[2] = a02 * b00 + a12 * b01 + a22 * b02; out[3] = a03 * b00 + a13 * b01 + a23 * b02; out[4] = a00 * b10 + a10 * b11 + a20 * b12; out[5] = a01 * b10 + a11 * b11 + a21 * b12; out[6] = a02 * b10 + a12 * b11 + a22 * b12; out[7] = a03 * b10 + a13 * b11 + a23 * b12; out[8] = a00 * b20 + a10 * b21 + a20 * b22; out[9] = a01 * b20 + a11 * b21 + a21 * b22; out[10] = a02 * b20 + a12 * b21 + a22 * b22; out[11] = a03 * b20 + a13 * b21 + a23 * b22; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } return out; }; /** * Rotates a matrix by the given angle around the X axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateX = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[4] = a10 * c + a20 * s; out[5] = a11 * c + a21 * s; out[6] = a12 * c + a22 * s; out[7] = a13 * c + a23 * s; out[8] = a20 * c - a10 * s; out[9] = a21 * c - a11 * s; out[10] = a22 * c - a12 * s; out[11] = a23 * c - a13 * s; return out; }; /** * Rotates a matrix by the given angle around the Y axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateY = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c - a20 * s; out[1] = a01 * c - a21 * s; out[2] = a02 * c - a22 * s; out[3] = a03 * c - a23 * s; out[8] = a00 * s + a20 * c; out[9] = a01 * s + a21 * c; out[10] = a02 * s + a22 * c; out[11] = a03 * s + a23 * c; return out; }; /** * Rotates a matrix by the given angle around the Z axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateZ = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c + a10 * s; out[1] = a01 * c + a11 * s; out[2] = a02 * c + a12 * s; out[3] = a03 * c + a13 * s; out[4] = a10 * c - a00 * s; out[5] = a11 * c - a01 * s; out[6] = a12 * c - a02 * s; out[7] = a13 * c - a03 * s; return out; }; /** * Creates a matrix from a quaternion rotation and vector translation * This is equivalent to (but much faster than): * * mat4.identity(dest); * mat4.translate(dest, vec); * var quatMat = mat4.create(); * quat4.toMat4(quat, quatMat); * mat4.multiply(dest, quatMat); * * @param {mat4} out mat4 receiving operation result * @param {quat4} q Rotation quaternion * @param {vec3} v Translation vector * @returns {mat4} out */ mat4.fromRotationTranslation = function (out, q, v) { // Quaternion math var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - (yy + zz); out[1] = xy + wz; out[2] = xz - wy; out[3] = 0; out[4] = xy - wz; out[5] = 1 - (xx + zz); out[6] = yz + wx; out[7] = 0; out[8] = xz + wy; out[9] = yz - wx; out[10] = 1 - (xx + yy); out[11] = 0; out[12] = v[0]; out[13] = v[1]; out[14] = v[2]; out[15] = 1; return out; }; mat4.fromQuat = function (out, q) { var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - yy - zz; out[1] = yx + wz; out[2] = zx - wy; out[3] = 0; out[4] = yx - wz; out[5] = 1 - xx - zz; out[6] = zy + wx; out[7] = 0; out[8] = zx + wy; out[9] = zy - wx; out[10] = 1 - xx - yy; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Generates a frustum matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {Number} left Left bound of the frustum * @param {Number} right Right bound of the frustum * @param {Number} bottom Bottom bound of the frustum * @param {Number} top Top bound of the frustum * @param {Number} near Near bound of the frustum * @param {Number} far Far bound of the frustum * @returns {mat4} out */ mat4.frustum = function (out, left, right, bottom, top, near, far) { var rl = 1 / (right - left), tb = 1 / (top - bottom), nf = 1 / (near - far); out[0] = (near * 2) * rl; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = (near * 2) * tb; out[6] = 0; out[7] = 0; out[8] = (right + left) * rl; out[9] = (top + bottom) * tb; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (far * near * 2) * nf; out[15] = 0; return out; }; /** * Generates a perspective projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} fovy Vertical field of view in radians * @param {number} aspect Aspect ratio. typically viewport width/height * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ mat4.perspective = function (out, fovy, aspect, near, far) { var f = 1.0 / Math.tan(fovy / 2), nf = 1 / (near - far); out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (2 * far * near) * nf; out[15] = 0; return out; }; /** * Generates a orthogonal projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} left Left bound of the frustum * @param {number} right Right bound of the frustum * @param {number} bottom Bottom bound of the frustum * @param {number} top Top bound of the frustum * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ mat4.ortho = function (out, left, right, bottom, top, near, far) { var lr = 1 / (left - right), bt = 1 / (bottom - top), nf = 1 / (near - far); out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 2 * nf; out[11] = 0; out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1; return out; }; /** * Generates a look-at matrix with the given eye position, focal point, and up axis * * @param {mat4} out mat4 frustum matrix will be written into * @param {vec3} eye Position of the viewer * @param {vec3} center Point the viewer is looking at * @param {vec3} up vec3 pointing up * @returns {mat4} out */ mat4.lookAt = function (out, eye, center, up) { var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, eyex = eye[0], eyey = eye[1], eyez = eye[2], upx = up[0], upy = up[1], upz = up[2], centerx = center[0], centery = center[1], centerz = center[2]; if (Math.abs(eyex - centerx) < GLMAT_EPSILON && Math.abs(eyey - centery) < GLMAT_EPSILON && Math.abs(eyez - centerz) < GLMAT_EPSILON) { return mat4.identity(out); } z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz; len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len; z1 *= len; z2 *= len; x0 = upy * z2 - upz * z1; x1 = upz * z0 - upx * z2; x2 = upx * z1 - upy * z0; len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (!len) { x0 = 0; x1 = 0; x2 = 0; } else { len = 1 / len; x0 *= len; x1 *= len; x2 *= len; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (!len) { y0 = 0; y1 = 0; y2 = 0; } else { len = 1 / len; y0 *= len; y1 *= len; y2 *= len; } out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0; out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0; out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0; out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); out[15] = 1; return out; }; /** * Returns a string representation of a mat4 * * @param {mat4} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat4.str = function (a) { return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; }; /** * Returns Frobenius norm of a mat4 * * @param {mat4} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat4.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) )) }; if(typeof(exports) !== 'undefined') { exports.mat4 = mat4; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class Quaternion * @name quat */ var quat = {}; /** * Creates a new identity quat * * @returns {quat} a new quaternion */ quat.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Sets a quaternion to represent the shortest rotation from one * vector to another. * * Both vectors are assumed to be unit length. * * @param {quat} out the receiving quaternion. * @param {vec3} a the initial vector * @param {vec3} b the destination vector * @returns {quat} out */ quat.rotationTo = (function() { var tmpvec3 = vec3.create(); var xUnitVec3 = vec3.fromValues(1,0,0); var yUnitVec3 = vec3.fromValues(0,1,0); return function(out, a, b) { var dot = vec3.dot(a, b); if (dot < -0.999999) { vec3.cross(tmpvec3, xUnitVec3, a); if (vec3.length(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a); vec3.normalize(tmpvec3, tmpvec3); quat.setAxisAngle(out, tmpvec3, Math.PI); return out; } else if (dot > 0.999999) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } else { vec3.cross(tmpvec3, a, b); out[0] = tmpvec3[0]; out[1] = tmpvec3[1]; out[2] = tmpvec3[2]; out[3] = 1 + dot; return quat.normalize(out, out); } }; })(); /** * Sets the specified quaternion with values corresponding to the given * axes. Each axis is a vec3 and is expected to be unit length and * perpendicular to all other specified axes. * * @param {vec3} view the vector representing the viewing direction * @param {vec3} right the vector representing the local "right" direction * @param {vec3} up the vector representing the local "up" direction * @returns {quat} out */ quat.setAxes = (function() { var matr = mat3.create(); return function(out, view, right, up) { matr[0] = right[0]; matr[3] = right[1]; matr[6] = right[2]; matr[1] = up[0]; matr[4] = up[1]; matr[7] = up[2]; matr[2] = -view[0]; matr[5] = -view[1]; matr[8] = -view[2]; return quat.normalize(out, quat.fromMat3(out, matr)); }; })(); /** * Creates a new quat initialized with values from an existing quaternion * * @param {quat} a quaternion to clone * @returns {quat} a new quaternion * @function */ quat.clone = vec4.clone; /** * Creates a new quat initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {quat} a new quaternion * @function */ quat.fromValues = vec4.fromValues; /** * Copy the values from one quat to another * * @param {quat} out the receiving quaternion * @param {quat} a the source quaternion * @returns {quat} out * @function */ quat.copy = vec4.copy; /** * Set the components of a quat to the given values * * @param {quat} out the receiving quaternion * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {quat} out * @function */ quat.set = vec4.set; /** * Set a quat to the identity quaternion * * @param {quat} out the receiving quaternion * @returns {quat} out */ quat.identity = function(out) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Sets a quat from the given angle and rotation axis, * then returns it. * * @param {quat} out the receiving quaternion * @param {vec3} axis the axis around which to rotate * @param {Number} rad the angle in radians * @returns {quat} out **/ quat.setAxisAngle = function(out, axis, rad) { rad = rad * 0.5; var s = Math.sin(rad); out[0] = s * axis[0]; out[1] = s * axis[1]; out[2] = s * axis[2]; out[3] = Math.cos(rad); return out; }; /** * Adds two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @returns {quat} out * @function */ quat.add = vec4.add; /** * Multiplies two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @returns {quat} out */ quat.multiply = function(out, a, b) { var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3]; out[0] = ax * bw + aw * bx + ay * bz - az * by; out[1] = ay * bw + aw * by + az * bx - ax * bz; out[2] = az * bw + aw * bz + ax * by - ay * bx; out[3] = aw * bw - ax * bx - ay * by - az * bz; return out; }; /** * Alias for {@link quat.multiply} * @function */ quat.mul = quat.multiply; /** * Scales a quat by a scalar number * * @param {quat} out the receiving vector * @param {quat} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {quat} out * @function */ quat.scale = vec4.scale; /** * Rotates a quaternion by the given angle about the X axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateX = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw + aw * bx; out[1] = ay * bw + az * bx; out[2] = az * bw - ay * bx; out[3] = aw * bw - ax * bx; return out; }; /** * Rotates a quaternion by the given angle about the Y axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateY = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], by = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw - az * by; out[1] = ay * bw + aw * by; out[2] = az * bw + ax * by; out[3] = aw * bw - ay * by; return out; }; /** * Rotates a quaternion by the given angle about the Z axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateZ = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], bz = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw + ay * bz; out[1] = ay * bw - ax * bz; out[2] = az * bw + aw * bz; out[3] = aw * bw - az * bz; return out; }; /** * Calculates the W component of a quat from the X, Y, and Z components. * Assumes that quaternion is 1 unit in length. * Any existing W component will be ignored. * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate W component of * @returns {quat} out */ quat.calculateW = function (out, a) { var x = a[0], y = a[1], z = a[2]; out[0] = x; out[1] = y; out[2] = z; out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); return out; }; /** * Calculates the dot product of two quat's * * @param {quat} a the first operand * @param {quat} b the second operand * @returns {Number} dot product of a and b * @function */ quat.dot = vec4.dot; /** * Performs a linear interpolation between two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {quat} out * @function */ quat.lerp = vec4.lerp; /** * Performs a spherical linear interpolation between two quat * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {quat} out */ quat.slerp = function (out, a, b, t) { // benchmarks: // http://jsperf.com/quaternion-slerp-implementations var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3]; var omega, cosom, sinom, scale0, scale1; // calc cosine cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary) if ( cosom < 0.0 ) { cosom = -cosom; bx = - bx; by = - by; bz = - bz; bw = - bw; } // calculate coefficients if ( (1.0 - cosom) > 0.000001 ) { // standard case (slerp) omega = Math.acos(cosom); sinom = Math.sin(omega); scale0 = Math.sin((1.0 - t) * omega) / sinom; scale1 = Math.sin(t * omega) / sinom; } else { // "from" and "to" quaternions are very close // ... so we can do a linear interpolation scale0 = 1.0 - t; scale1 = t; } // calculate final values out[0] = scale0 * ax + scale1 * bx; out[1] = scale0 * ay + scale1 * by; out[2] = scale0 * az + scale1 * bz; out[3] = scale0 * aw + scale1 * bw; return out; }; /** * Calculates the inverse of a quat * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate inverse of * @returns {quat} out */ quat.invert = function(out, a) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, invDot = dot ? 1.0/dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 out[0] = -a0*invDot; out[1] = -a1*invDot; out[2] = -a2*invDot; out[3] = a3*invDot; return out; }; /** * Calculates the conjugate of a quat * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate conjugate of * @returns {quat} out */ quat.conjugate = function (out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a[3]; return out; }; /** * Calculates the length of a quat * * @param {quat} a vector to calculate length of * @returns {Number} length of a * @function */ quat.length = vec4.length; /** * Alias for {@link quat.length} * @function */ quat.len = quat.length; /** * Calculates the squared length of a quat * * @param {quat} a vector to calculate squared length of * @returns {Number} squared length of a * @function */ quat.squaredLength = vec4.squaredLength; /** * Alias for {@link quat.squaredLength} * @function */ quat.sqrLen = quat.squaredLength; /** * Normalize a quat * * @param {quat} out the receiving quaternion * @param {quat} a quaternion to normalize * @returns {quat} out * @function */ quat.normalize = vec4.normalize; /** * Creates a quaternion from the given 3x3 rotation matrix. * * NOTE: The resultant quaternion is not normalized, so you should be sure * to renormalize the quaternion yourself where necessary. * * @param {quat} out the receiving quaternion * @param {mat3} m rotation matrix * @returns {quat} out * @function */ quat.fromMat3 = function(out, m) { // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes // article "Quaternion Calculus and Fast Animation". var fTrace = m[0] + m[4] + m[8]; var fRoot; if ( fTrace > 0.0 ) { // |w| > 1/2, may as well choose w > 1/2 fRoot = Math.sqrt(fTrace + 1.0); // 2w out[3] = 0.5 * fRoot; fRoot = 0.5/fRoot; // 1/(4w) out[0] = (m[7]-m[5])*fRoot; out[1] = (m[2]-m[6])*fRoot; out[2] = (m[3]-m[1])*fRoot; } else { // |w| <= 1/2 var i = 0; if ( m[4] > m[0] ) i = 1; if ( m[8] > m[i*3+i] ) i = 2; var j = (i+1)%3; var k = (i+2)%3; fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); out[i] = 0.5 * fRoot; fRoot = 0.5 / fRoot; out[3] = (m[k*3+j] - m[j*3+k]) * fRoot; out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; } return out; }; /** * Returns a string representation of a quatenion * * @param {quat} vec vector to represent as a string * @returns {String} string representation of the vector */ quat.str = function (a) { return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; if(typeof(exports) !== 'undefined') { exports.quat = quat; } ; })(shim.exports); })(this); },{}],105:[function(require,module,exports){ 'use strict'; function constant(value) { return function() { return value; } } function interpolateNumber(a, b, t) { return (a * (1 - t)) + (b * t); } function interpolateArray(a, b, t) { var result = []; for (var i = 0; i < a.length; i++) { result[i] = interpolateNumber(a[i], b[i], t); } return result; } exports['interpolated'] = function(f) { if (!f.stops) { return constant(f); } var stops = f.stops, base = f.base || 1, interpolate = Array.isArray(stops[0][1]) ? interpolateArray : interpolateNumber; return function(z) { // find the two stops which the current z is between var low, high; for (var i = 0; i < stops.length; i++) { var stop = stops[i]; if (stop[0] <= z) { low = stop; } if (stop[0] > z) { high = stop; break; } } if (low && high) { var zoomDiff = high[0] - low[0], zoomProgress = z - low[0], t = base === 1 ? zoomProgress / zoomDiff : (Math.pow(base, zoomProgress) - 1) / (Math.pow(base, zoomDiff) - 1); return interpolate(low[1], high[1], t); } else if (low) { return low[1]; } else if (high) { return high[1]; } }; }; exports['piecewise-constant'] = function(f) { if (!f.stops) { return constant(f); } var stops = f.stops; return function(z) { for (var i = 0; i < stops.length; i++) { if (stops[i][0] > z) { return stops[i === 0 ? 0 : i - 1][1]; } } return stops[stops.length - 1][1]; } }; },{}],106:[function(require,module,exports){ 'use strict'; var reference = require('../../reference/latest.js'); var validate = require('./parsed'); module.exports = function(style) { return validate(style, reference); }; },{"../../reference/latest.js":108,"./parsed":107}],107:[function(require,module,exports){ 'use strict'; var parseCSSColor = require('csscolorparser').parseCSSColor; var format = require('util').format; module.exports = function(style, reference) { var constants = style.constants || {}, layers = {}, errors = []; function error(key, val /*, message, ...*/) { var err = { message: (key ? key + ': ' : '') + format.apply(format, Array.prototype.slice.call(arguments, 2)) }; if (val !== null && val !== undefined && val.__line__) { err.line = val.__line__; } errors.push(err); } // Main recursive validation function. Tracks: // // - key: string representing location of validation in style tree. Used only // for more informative error reporting. // - val: current value from style being evaluated. May be anything from a // high level object that needs to be descended into deeper or a simple // scalar value. // - spec: current spec being evaluated. Tracks val. // function validate(key, val, spec) { var type = typeof_(val); // Constants if (type === 'string' && val[0] === '@') { if (!(val in constants)) { return error(key, val, 'constant "%s" not found', val); } val = constants[val]; type = typeof_(val); } // Functions if (spec.function && type === 'object') { return validate.function(key, val, spec); } if (spec.type) { var validator = validate[spec.type]; if (validator) { return validator(key, val, spec); } spec = reference[spec.type]; } validate.object(key, val, spec); } validate.constants = function(key, val) { var type = typeof_(val); if (type !== 'object') { return error(key, val, 'object expected, %s found', type); } for (var k in val) { if (k[0] !== '@') { error(key + '.' + k, val[k], 'constants must start with "@"'); } } }; validate.source = function(key, val) { if (!val.type) { error(key, val, '"type" is required'); return; } var type = unbundle(val.type); switch (type) { case 'vector': case 'raster': validate.object(key, val, reference.source_tile); if ('url' in val) { for (var prop in val) { if (['type', 'url', 'tileSize'].indexOf(prop) < 0) { error(key + '.' + prop, val[prop], 'a source with a "url" property may not include a "%s" property', prop); } } } break; case 'geojson': validate.object(key, val, reference.source_geojson); break; case 'video': validate.object(key, val, reference.source_video); break; default: validate.enum(key + '.type', val.type, {values: ['vector', 'raster', 'geojson', 'video']}); } }; validate.layer = function(key, val) { if (!val.type && !val.ref) { error(key, val, 'either "type" or "ref" is required'); } var type = unbundle(val.type), ref = unbundle(val.ref); if (val.id) { if (layers[val.id]) { error(key, val.id, 'duplicate layer id "%s", previously used at line %d', val.id, layers[val.id]); } else { layers[val.id] = val.id.__line__; } } if ('ref' in val) { ['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) { if (p in val) { error(key, val[p], '"%s" is prohibited for ref layers', p); } }); var parent; style.layers.forEach(function(layer) { if (layer.id == ref) parent = layer; }); if (!parent) { error(key, val.ref, 'ref layer "%s" not found', ref); } else if (parent.ref) { error(key, val.ref, 'ref cannot reference another ref layer'); } else { type = parent.type; } } else if (type !== 'background') { if (!val.source) { error(key, val, 'missing required property "source"'); } else { var source = style.sources[val.source]; if (!source) { error(key, val.source, 'source "%s" not found', val.source); } else if (source.type == 'vector' && type == 'raster') { error(key, val.source, 'layer "%s" requires a raster source', val.id); } else if (source.type == 'raster' && type != 'raster') { error(key, val.source, 'layer "%s" requires a vector source', val.id); } } } validate.object(key, val, reference.layer, { filter: validate.filter, layout: function(key, val) { var spec = reference['layout_' + type]; return type && spec && validate(key, val, spec); }, paint: function(key, val) { var spec = reference['paint_' + type]; return type && spec && validate(key, val, spec); } }); }; validate.object = function (key, val, spec, validators) { validators = validators || {}; var type = typeof_(val); if (type !== 'object') { return error(key, val, 'object expected, %s found', type); } for (var k in val) { var speckey = k.split('.')[0]; // treat 'paint.*' as 'paint' var def = spec[speckey] || spec['*']; var transition = speckey.match(/^(.*)-transition$/); if (def) { (validators[speckey] || validate)((key ? key + '.' : key) + k, val[k], def); } else if (transition && spec[transition[1]] && spec[transition[1]].transition) { validate((key ? key + '.' : key) + k, val[k], reference.transition); // tolerate root-level extra keys & arbitrary layer properties } else if (key !== '' && key.split('.').length !== 1) { error(key, val[k], 'unknown property "%s"', k); } } for (var l in spec) { if (spec[l].required && spec[l]['default'] === undefined && val[l] === undefined) { error(key, val, 'missing required property "%s"', l); } } }; validate.array = function (key, val, spec, validator) { if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (spec.length && val.length !== spec.length) { return error(key, val, 'array length %d expected, length %d found', spec.length, val.length); } var value = { "type": spec.value }; if (style.version < 7) { value.function = spec.function; } if (typeof_(spec.value) === 'object') { value = spec.value; } for (var i = 0; i < val.length; i++) { (validator || validate)(key + '[' + i + ']', val[i], value); } }; validate.filter = function(key, val) { var type; if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (val.length < 1) { return error(key, val, 'filter array must have at least 1 element'); } validate.enum(key + '[0]', val[0], reference.filter_operator); switch (unbundle(val[0])) { case '<': case '<=': case '>': case '>=': if (val.length >= 2 && val[1] == '$type') { error(key, val, '"$type" cannot be use with operator "%s"', val[0]); } /* falls through */ case '==': case '!=': if (val.length != 3) { error(key, val, 'filter array for operator "%s" must have 3 elements', val[0]); } /* falls through */ case 'in': case '!in': if (val.length >= 2) { type = typeof_(val[1]); if (type !== 'string') { error(key + '[1]', val[1], 'string expected, %s found', type); } else if (val[1][0] === '@') { error(key + '[1]', val[1], 'filter key cannot be a constant'); } } for (var i = 2; i < val.length; i++) { type = typeof_(val[i]); if (val[1] == '$type') { validate.enum(key + '[' + i + ']', val[i], reference.geometry_type); } else if (type === 'string' && val[i][0] === '@') { error(key + '[' + i + ']', val[i], 'filter value cannot be a constant'); } else if (type !== 'string' && type !== 'number' && type !== 'boolean') { error(key + '[' + i + ']', val[i], 'string, number, or boolean expected, %s found', type); } } break; case 'any': case 'all': case 'none': for (i = 1; i < val.length; i++) { validate.filter(key + '[' + i + ']', val[i]); } break; } }; validate.function = function(key, val, spec) { validate.object(key, val, reference.function, { stops: function (key, val, arraySpec) { var lastStop = -Infinity; validate.array(key, val, arraySpec, function validateStop(key, val) { if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (val.length !== 2) { return error(key, val, 'array length %d expected, length %d found', 2, val.length); } validate(key + '[0]', val[0], {type: 'number'}); validate(key + '[1]', val[1], spec); if (typeof_(val[0]) === 'number') { if (spec.function === 'piecewise-constant' && val[0] % 1 !== 0) { error(key + '[0]', val[0], 'zoom level for piecewise-constant functions must be an integer'); } if (val[0] < lastStop) { error(key + '[0]', val[0], 'array stops must appear in ascending order'); } lastStop = val[0]; } }); if (typeof_(val) === 'array' && val.length === 0) { error(key, val, 'array must have at least one stop'); } } }); }; validate.enum = function (key, val, spec) { if (spec.values.indexOf(unbundle(val)) === -1) { error(key, val, 'expected one of [%s], %s found', spec.values.join(', '), val); } }; validate.color = function(key, val) { var type = typeof_(val); if (type !== 'string') { error(key, val, 'color expected, %s found', type); } else if (parseCSSColor(val) === null) { error(key, val, 'color expected, "%s" found', val); } }; function typeValidator(expected) { return function(key, val, spec) { var actual = typeof_(val); if (actual !== expected) { error(key, val, '%s expected, %s found', expected, actual); } if ('minimum' in spec && val < spec.minimum) { error(key, val, '%s is less than the minimum value %s', val, spec.minimum); } if ('maximum' in spec && val > spec.maximum) { error(key, val, '%s is greater than the maximum value %s', val, spec.maximum); } }; } validate.number = typeValidator('number'); validate.string = typeValidator('string'); validate.boolean = typeValidator('boolean'); validate['*'] = function() {}; validate('', style, reference.$root); return errors; }; function typeof_(val) { if (val instanceof Number) return 'number'; if (val instanceof String) return 'string'; if (val instanceof Boolean) return 'boolean'; if (Array.isArray(val)) return 'array'; if (val === null) return 'null'; return typeof val; } function unbundle(_) { if (_ instanceof Number || _ instanceof String || _ instanceof Boolean) { return _.valueOf(); } else { return _; } } },{"csscolorparser":97,"util":124}],108:[function(require,module,exports){ module.exports = require('./v7.json'); },{"./v7.json":109}],109:[function(require,module,exports){ module.exports={ "$version": 7, "$root": { "version": { "required": true, "type": "enum", "values": [ 7 ], "doc": "Stylesheet version number. Must be 7." }, "name": { "type": "string", "doc": "A human-readable name for the style." }, "constants": { "type": "constants", "doc": "An object of constants to be referenced in layers." }, "sources": { "required": true, "type": "sources", "doc": "Data source specifications." }, "sprite": { "type": "string", "doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended." }, "glyphs": { "type": "string", "doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}." }, "transition": { "type": "transition", "doc": "A global transition definition to use as a default across properties." }, "layers": { "required": true, "type": "array", "value": "layer", "doc": "Layers will be drawn in the order of this array." } }, "constants": { "*": { "type": "*", "doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol." } }, "sources": { "*": { "type": "source", "doc": "Specification of a data source. For vector and raster sources, either TileJSON or a URL to a TileJSON must be provided. For GeoJSON and video sources, a URL must be provided." } }, "source": [ "source_tile", "source_geojson", "source_video" ], "source_tile": { "type": { "required": true, "type": "enum", "values": [ "vector", "raster" ], "doc": "The data type of the source." }, "url": { "type": "string", "doc": "A URL to a TileJSON resource. Supported protocols are `http:`, `https:`, and `mapbox://<mapid>`." }, "tiles": { "type": "array", "value": "string", "doc": "An array of one or more tile source URLs, as in the TileJSON spec." }, "minzoom": { "type": "number", "default": 0, "doc": "Minimum zoom level for which tiles are available, as in the TileJSON spec." }, "maxzoom": { "type": "number", "default": 22, "doc": "Maximum zoom level for which tiles are available, as in the TileJSON spec. Data from tiles at the maxzoom are used when displaying the map at higher zoom levels." }, "tileSize": { "type": "number", "default": 512, "units": "pixels", "doc": "The minimum visual size to display tiles for this layer. Only configurable for raster layers." }, "*": { "type": "*", "doc": "Other keys to configure the data source." } }, "source_geojson": { "type": { "required": true, "type": "enum", "values": [ "geojson" ] }, "data": { "type": "*" } }, "source_video": { "type": { "required": true, "type": "enum", "values": [ "video" ] }, "url": { "required": true, "type": "array", "value": "string", "doc": "URLs to video content in order of preferred format." }, "coordinates": { "required": true, "type": "array", "length": 4, "value": { "type": "array", "length": 2, "value": "number" } } }, "layer": { "id": { "type": "string", "doc": "Unique layer name." }, "type": { "type": "enum", "values": [ "fill", "line", "symbol", "raster", "background" ], "doc": "Rendering type of this layer." }, "ref": { "type": "string", "doc": "References another layer to copy `type`, `source`, `source-layer`, `minzoom`, `maxzoom`, `filter`, and `layout` properties from. This allows the layers to share processing and be more efficient." }, "source": { "type": "string", "doc": "Name of a source description to be used for this layer." }, "source-layer": { "type": "string", "doc": "Layer to use from a vector tile source. Required if the source supports multiple layers." }, "minzoom": { "type": "number", "minimum": 0, "maximum": 22, "doc": "The minimum zoom level on which the layer gets parsed and appears on." }, "maxzoom": { "type": "number", "minimum": 0, "maximum": 22, "doc": "The maximum zoom level on which the layer gets parsed and appears on." }, "interactive": { "type": "boolean", "doc": "Enable querying of feature data from this layer for interactivity.", "default": false }, "filter": { "type": "filter", "doc": "A expression specifying conditions on source features. Only features that match the filter are displayed." }, "layout": { "type": "layout", "doc": "Layout properties for the layer." }, "paint": { "type": "paint", "doc": "Default paint properties for this layer." }, "paint.*": { "type": "paint", "doc": "Class-specific paint properties for this layer. The class name is the part after the first dot." } }, "layout": [ "layout_fill", "layout_line", "layout_symbol", "layout_raster", "layout_background" ], "layout_background": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_fill": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_line": { "line-cap": { "type": "enum", "function": "piecewise-constant", "values": [ "butt", "round", "square" ], "default": "butt", "doc": "The display of line endings." }, "line-join": { "type": "enum", "function": "piecewise-constant", "values": [ "bevel", "round", "miter" ], "default": "miter", "doc": "The display of lines when joining." }, "line-miter-limit": { "type": "number", "default": 2, "function": "interpolated", "doc": "Used to automatically convert miter joins to bevel joins for sharp angles.", "requires": [ { "line-join": "miter" } ] }, "line-round-limit": { "type": "number", "default": 1, "function": "interpolated", "doc": "Used to automatically convert round joins to miter joins for shallow angles.", "requires": [ { "line-join": "round" } ] }, "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_symbol": { "symbol-placement": { "type": "enum", "function": "piecewise-constant", "values": [ "point", "line" ], "default": "point", "doc": "Label placement relative to its geometry. `line` can only be used on LineStrings and Polygons." }, "symbol-min-distance": { "type": "number", "default": 250, "minimum": 1, "function": "interpolated", "units": "pixels", "doc": "Minimum distance between two symbol anchors.", "requires": [ { "symbol-placement": "line" } ] }, "symbol-avoid-edges": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer." }, "icon-allow-overlap": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon will be visible even if it collides with other icons and text.", "requires": [ "icon-image" ] }, "icon-ignore-placement": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon won't affect placement of other icons and text.", "requires": [ "icon-image" ] }, "icon-optional": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbol will appear without its icon, in spaces where the icon would make it too large to fit.", "requires": [ "icon-image", "text-field" ] }, "icon-rotation-alignment": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon when map is rotated.", "requires": [ "icon-image" ] }, "icon-max-size": { "type": "number", "default": 1, "minimum": 0, "function": "interpolated", "doc": "The maximum factor to scale the icon.", "requires": [ "icon-image" ] }, "icon-image": { "type": "string", "function": "piecewise-constant", "doc": "A string with {tokens} replaced, referencing the data property to pull from.", "tokens": true }, "icon-rotate": { "type": "number", "default": 0, "period": 360, "function": "interpolated", "units": "degrees", "doc": "Rotates the icon clockwise.", "requires": [ "icon-image" ] }, "icon-padding": { "type": "number", "default": 2, "minimum": 0, "function": "interpolated", "units": "pixels", "doc": "Padding value around icon bounding box to avoid icon collisions.", "requires": [ "icon-image" ] }, "icon-keep-upright": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon may be flipped to prevent it from being rendered upside-down", "requires": [ "icon-image", { "icon-rotation-alignment": "map" } ] }, "icon-offset": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "doc": "Icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "icon-image" ] }, "text-rotation-alignment": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon or text when map is rotated.", "requires": [ "text-field" ] }, "text-field": { "type": "string", "function": "piecewise-constant", "default": "", "tokens": true, "doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}." }, "text-font": { "type": "string", "function": "piecewise-constant", "default": "Open Sans Regular, Arial Unicode MS Regular", "doc": "Font stack to use for displaying text.", "requires": [ "text-field" ] }, "text-max-size": { "type": "number", "default": 16, "minimum": 0, "units": "pixels", "function": "interpolated", "doc": "The maximum size text will be laid out, to calculate collisions with.", "requires": [ "text-field" ] }, "text-max-width": { "type": "number", "default": 15, "minimum": 0, "units": "em", "function": "interpolated", "doc": "The maximum line width for text wrapping.", "requires": [ "text-field" ] }, "text-line-height": { "type": "number", "default": 1.2, "units": "em", "function": "interpolated", "doc": "Text leading value for multi-line text.", "requires": [ "text-field" ] }, "text-letter-spacing": { "type": "number", "default": 0, "units": "em", "function": "interpolated", "doc": "Text kerning value.", "requires": [ "text-field" ] }, "text-justify": { "type": "enum", "function": "piecewise-constant", "values": [ "left", "center", "right" ], "default": "center", "doc": "Text justification options.", "requires": [ "text-field" ] }, "text-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "center", "left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right" ], "default": "center", "doc": "Which part of the text to place closest to the anchor.", "requires": [ "text-field" ] }, "text-max-angle": { "type": "number", "default": 45, "units": "degrees", "function": "interpolated", "doc": "Maximum angle change between adjacent characters.", "requires": [ "text-field", { "symbol-placement": "line" } ] }, "text-rotate": { "type": "number", "default": 0, "period": 360, "units": "degrees", "function": "interpolated", "doc": "Rotates the text clockwise.", "requires": [ "text-field" ] }, "text-padding": { "type": "number", "default": 2, "minimum": 0, "units": "pixels", "function": "interpolated", "doc": "Padding value around text bounding box to avoid label collisions.", "requires": [ "text-field" ] }, "text-keep-upright": { "type": "boolean", "function": "piecewise-constant", "default": true, "doc": "If true, the text may be flipped vertically to prevent it from being rendered upside-down.", "requires": [ "text-field", { "text-rotation-alignment": "map" } ] }, "text-transform": { "type": "enum", "function": "piecewise-constant", "values": [ "none", "uppercase", "lowercase" ], "default": "none", "doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property.", "requires": [ "text-field" ] }, "text-offset": { "type": "array", "doc": "Specifies the distance that text is offset from its anchor horizontally and vertically.", "value": "number", "units": "ems", "function": "interpolated", "length": 2, "default": [ 0, 0 ], "requires": [ "text-field" ] }, "text-allow-overlap": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the text will be visible even if it collides with other icons and labels.", "requires": [ "text-field" ] }, "text-ignore-placement": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the text won't affect placement of other icons and labels.", "requires": [ "text-field" ] }, "text-optional": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbol will appear without its text, in spaces where the text would make it too large to fit.", "requires": [ "text-field", "icon-image" ] }, "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_raster": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "filter": { "type": "array", "value": "*" }, "filter_operator": { "type": "enum", "values": [ "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none" ] }, "geometry_type": { "type": "enum", "values": [ "Point", "LineString", "Polygon" ] }, "function": { "stops": { "type": "array", "required": true, "doc": "An array of stops.", "value": "function_stop" }, "base": { "type": "number", "default": 1, "minimum": 0, "doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly." } }, "function_stop": { "type": "array", "minimum": 0, "maximum": 22, "value": [ "number", "color" ], "length": 2, "doc": "Zoom level and value pair." }, "paint": [ "paint_fill", "paint_line", "paint_symbol", "paint_raster", "paint_background" ], "paint_fill": { "fill-antialias": { "type": "boolean", "function": "piecewise-constant", "default": true, "doc": "Whether or not the fill should be antialiased." }, "fill-opacity": { "type": "number", "function": "interpolated", "default": 1, "minimum": 0, "maximum": 1, "doc": "The opacity given to the fill color.", "transition": true }, "fill-color": { "type": "color", "default": "#000000", "doc": "The color of the fill.", "function": "interpolated", "transition": true, "requires": [ { "!": "fill-image" } ] }, "fill-outline-color": { "type": "color", "doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.", "function": "interpolated", "transition": true, "requires": [ { "!": "fill-image" }, { "fill-antialias": true } ] }, "fill-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." }, "fill-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "fill-translate" ] }, "fill-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Name of image in sprite to use for drawing image fills." } }, "paint_line": { "line-opacity": { "type": "number", "doc": "The opacity at which the line will be drawn.", "function": "interpolated", "default": 1, "minimum": 0, "maximum": 1, "transition": true }, "line-color": { "type": "color", "doc": "The color with which the line will be drawn.", "default": "#000000", "function": "interpolated", "transition": true, "requires": [ { "!": "line-image" } ] }, "line-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." }, "line-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "line-translate" ] }, "line-width": { "type": "number", "default": 1, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Stroke thickness." }, "line-gap-width": { "type": "number", "default": 0, "minimum": 0, "doc": "Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.", "function": "interpolated", "transition": true, "units": "pixels" }, "line-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Blur applied to the line, in pixels." }, "line-dasharray": { "type": "array", "function": "piecewise-constant", "value": "number", "doc": "Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.", "minimum": 0, "transition": true, "units": "line widths", "requires": [ { "!": "line-image" } ] }, "line-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Name of image in sprite to use for drawing image lines." } }, "paint_symbol": { "icon-opacity": { "doc": "The opacity at which the icon will be drawn.", "type": "number", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true, "requires": [ "icon-image" ] }, "icon-size": { "type": "number", "default": 1, "function": "interpolated", "transition": true, "doc": "Scale factor for icon. 1 is original size, 3 triples the size.", "requires": [ "icon-image" ] }, "icon-color": { "type": "color", "default": "#000000", "function": "interpolated", "transition": true, "doc": "The color of the icon. This can only be used with sdf icons.", "requires": [ "icon-image" ] }, "icon-halo-color": { "type": "color", "default": "rgba(0, 0, 0, 0)", "function": "interpolated", "transition": true, "doc": "The color of the icon's halo. Icon halos can only be used with sdf icons.", "requires": [ "icon-image" ] }, "icon-halo-width": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Distance of halo to the icon outline.", "requires": [ "icon-image" ] }, "icon-halo-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Fade out the halo towards the outside.", "requires": [ "icon-image" ] }, "icon-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "An icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "icon-image" ] }, "icon-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "icon-image", "icon-translate" ] }, "text-opacity": { "type": "number", "doc": "The opacity at which the text will be drawn.", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true, "requires": [ "text-field" ] }, "text-size": { "type": "number", "default": 16, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Font size. If unspecified, the text will be as big as allowed by the layer definition.", "requires": [ "text-field" ] }, "text-color": { "type": "color", "doc": "The color with which the text will be drawn.", "default": "#000000", "function": "interpolated", "transition": true, "requires": [ "text-field" ] }, "text-halo-color": { "type": "color", "default": "rgba(0, 0, 0, 0)", "function": "interpolated", "transition": true, "doc": "The color of the text's halo, which helps it stand out from backgrounds.", "requires": [ "text-field" ] }, "text-halo-width": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.", "requires": [ "text-field" ] }, "text-halo-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "The halo's fadeout distance towards the outside.", "requires": [ "text-field" ] }, "text-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "Label offset. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "text-field" ] }, "text-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "text-field", "text-translate" ] } }, "paint_raster": { "raster-opacity": { "type": "number", "doc": "The opacity at which the image will be drawn.", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true }, "raster-hue-rotate": { "type": "number", "default": 0, "period": 360, "function": "interpolated", "transition": true, "units": "degrees", "doc": "Rotates hues around the color wheel." }, "raster-brightness-min": { "type": "number", "function": "interpolated", "doc": "Increase or reduce the brightness of the image. The value is the minimum brightness.", "default": 0, "minimum": 0, "maximum": 1, "transition": true }, "raster-brightness-max": { "type": "number", "function": "interpolated", "doc": "Increase or reduce the brightness of the image. The value is the maximum brightness.", "default": 1, "minimum": 0, "maximum": 1, "transition": true }, "raster-saturation": { "type": "number", "doc": "Increase or reduce the saturation of the image.", "default": 0, "minimum": -1, "maximum": 1, "function": "interpolated", "transition": true }, "raster-contrast": { "type": "number", "doc": "Increase or reduce the contrast of the image.", "default": 0, "minimum": -1, "maximum": 1, "function": "interpolated", "transition": true }, "raster-fade-duration": { "type": "number", "default": 300, "minimum": 0, "function": "interpolated", "transition": true, "units": "milliseconds", "doc": "Fade duration when a new tile is added." } }, "paint_background": { "background-color": { "type": "color", "default": "#000000", "doc": "The color with which the background will be drawn.", "function": "interpolated", "transition": true, "requires": [ { "!": "background-image" } ] }, "background-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Optionally an image which is drawn as the background." }, "background-opacity": { "type": "number", "default": 1, "minimum": 0, "maximum": 1, "doc": "The opacity at which the background will be drawn.", "function": "interpolated", "transition": true } }, "transition": { "duration": { "type": "number", "default": 300, "minimum": 0, "units": "milliseconds", "doc": "Time allotted for transitions to complete." }, "delay": { "type": "number", "default": 0, "minimum": 0, "units": "milliseconds", "doc": "Length of time before a transition begins." } } } },{}],110:[function(require,module,exports){ 'use strict'; // lightweight Buffer shim for pbf browser build // based on code from github.com/feross/buffer (MIT-licensed) module.exports = Buffer; var ieee754 = require('ieee754'); var BufferMethods; function Buffer(length) { var arr; if (length && length.length) { arr = length; length = arr.length; } var buf = new Uint8Array(length || 0); if (arr) buf.set(arr); buf.readUInt32LE = BufferMethods.readUInt32LE; buf.writeUInt32LE = BufferMethods.writeUInt32LE; buf.readInt32LE = BufferMethods.readInt32LE; buf.writeInt32LE = BufferMethods.writeInt32LE; buf.readFloatLE = BufferMethods.readFloatLE; buf.writeFloatLE = BufferMethods.writeFloatLE; buf.readDoubleLE = BufferMethods.readDoubleLE; buf.writeDoubleLE = BufferMethods.writeDoubleLE; buf.toString = BufferMethods.toString; buf.write = BufferMethods.write; buf.slice = BufferMethods.slice; buf.copy = BufferMethods.copy; buf._isBuffer = true; return buf; } var lastStr, lastStrEncoded; BufferMethods = { readUInt32LE: function(pos) { return ((this[pos]) | (this[pos + 1] << 8) | (this[pos + 2] << 16)) + (this[pos + 3] * 0x1000000); }, writeUInt32LE: function(val, pos) { this[pos] = val; this[pos + 1] = (val >>> 8); this[pos + 2] = (val >>> 16); this[pos + 3] = (val >>> 24); }, readInt32LE: function(pos) { return ((this[pos]) | (this[pos + 1] << 8) | (this[pos + 2] << 16)) + (this[pos + 3] << 24); }, readFloatLE: function(pos) { return ieee754.read(this, pos, true, 23, 4); }, readDoubleLE: function(pos) { return ieee754.read(this, pos, true, 52, 8); }, writeFloatLE: function(val, pos) { return ieee754.write(this, val, pos, true, 23, 4); }, writeDoubleLE: function(val, pos) { return ieee754.write(this, val, pos, true, 52, 8); }, toString: function(encoding, start, end) { var str = '', tmp = ''; start = start || 0; end = Math.min(this.length, end || this.length); for (var i = start; i < end; i++) { var ch = this[i]; if (ch <= 0x7F) { str += decodeURIComponent(tmp) + String.fromCharCode(ch); tmp = ''; } else { tmp += '%' + ch.toString(16); } } str += decodeURIComponent(tmp); return str; }, write: function(str, pos) { var bytes = str === lastStr ? lastStrEncoded : encodeString(str); for (var i = 0; i < bytes.length; i++) { this[pos + i] = bytes[i]; } }, slice: function(start, end) { return this.subarray(start, end); }, copy: function(buf, pos) { pos = pos || 0; for (var i = 0; i < this.length; i++) { buf[pos + i] = this[i]; } } }; BufferMethods.writeInt32LE = BufferMethods.writeUInt32LE; Buffer.byteLength = function(str) { lastStr = str; lastStrEncoded = encodeString(str); return lastStrEncoded.length; }; Buffer.isBuffer = function(buf) { return !!(buf && buf._isBuffer); }; function encodeString(str) { var length = str.length, bytes = []; for (var i = 0, c, lead; i < length; i++) { c = str.charCodeAt(i); // code point if (c > 0xD7FF && c < 0xE000) { if (lead) { if (c < 0xDC00) { bytes.push(0xEF, 0xBF, 0xBD); lead = c; continue; } else { c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000; lead = null; } } else { if (c > 0xDBFF || (i + 1 === length)) bytes.push(0xEF, 0xBF, 0xBD); else lead = c; continue; } } else if (lead) { bytes.push(0xEF, 0xBF, 0xBD); lead = null; } if (c < 0x80) bytes.push(c); else if (c < 0x800) bytes.push(c >> 0x6 | 0xC0, c & 0x3F | 0x80); else if (c < 0x10000) bytes.push(c >> 0xC | 0xE0, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80); else bytes.push(c >> 0x12 | 0xF0, c >> 0xC & 0x3F | 0x80, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80); } return bytes; } },{"ieee754":112}],111:[function(require,module,exports){ (function (global){ 'use strict'; module.exports = Pbf; var Buffer = global.Buffer || require('./buffer'); function Pbf(buf) { this.buf = !Buffer.isBuffer(buf) ? new Buffer(buf || 0) : buf; this.pos = 0; this.length = this.buf.length; } Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64 Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32 var SHIFT_LEFT_32 = (1 << 16) * (1 << 16), SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32, POW_2_63 = Math.pow(2, 63); Pbf.prototype = { destroy: function() { this.buf = null; }, // === READING ================================================================= readFields: function(readField, result, end) { end = end || this.length; while (this.pos < end) { var val = this.readVarint(), tag = val >> 3, startPos = this.pos; readField(tag, result, this); if (this.pos === startPos) this.skip(val); } return result; }, readMessage: function(readField, result) { return this.readFields(readField, result, this.readVarint() + this.pos); }, readFixed32: function() { var val = this.buf.readUInt32LE(this.pos); this.pos += 4; return val; }, readSFixed32: function() { var val = this.buf.readInt32LE(this.pos); this.pos += 4; return val; }, // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed) readFixed64: function() { var val = this.buf.readUInt32LE(this.pos) + this.buf.readUInt32LE(this.pos + 4) * SHIFT_LEFT_32; this.pos += 8; return val; }, readSFixed64: function() { var val = this.buf.readUInt32LE(this.pos) + this.buf.readInt32LE(this.pos + 4) * SHIFT_LEFT_32; this.pos += 8; return val; }, readFloat: function() { var val = this.buf.readFloatLE(this.pos); this.pos += 4; return val; }, readDouble: function() { var val = this.buf.readDoubleLE(this.pos); this.pos += 8; return val; }, readVarint: function() { var buf = this.buf, val, b, b0, b1, b2, b3; b0 = buf[this.pos++]; if (b0 < 0x80) return b0; b0 = b0 & 0x7f; b1 = buf[this.pos++]; if (b1 < 0x80) return b0 | b1 << 7; b1 = (b1 & 0x7f) << 7; b2 = buf[this.pos++]; if (b2 < 0x80) return b0 | b1 | b2 << 14; b2 = (b2 & 0x7f) << 14; b3 = buf[this.pos++]; if (b3 < 0x80) return b0 | b1 | b2 | b3 << 21; val = b0 | b1 | b2 | (b3 & 0x7f) << 21; b = buf[this.pos++]; val += (b & 0x7f) * 0x10000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x800000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x40000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x2000000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x100000000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x8000000000000000; if (b < 0x80) return val; throw new Error('Expected varint not more than 10 bytes'); }, readVarint64: function() { var startPos = this.pos, val = this.readVarint(); if (val < POW_2_63) return val; var pos = this.pos - 2; while (this.buf[pos] === 0xff) pos--; if (pos < startPos) pos = startPos; val = 0; for (var i = 0; i < pos - startPos + 1; i++) { var b = ~this.buf[startPos + i] & 0x7f; val += i < 4 ? b << i * 7 : b * Math.pow(2, i * 7); } return -val - 1; }, readSVarint: function() { var num = this.readVarint(); return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding }, readBoolean: function() { return Boolean(this.readVarint()); }, readString: function() { var end = this.readVarint() + this.pos, str = this.buf.toString('utf8', this.pos, end); this.pos = end; return str; }, readBytes: function() { var end = this.readVarint() + this.pos, buffer = this.buf.slice(this.pos, end); this.pos = end; return buffer; }, // verbose for performance reasons; doesn't affect gzipped size readPackedVarint: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readVarint()); return arr; }, readPackedSVarint: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSVarint()); return arr; }, readPackedBoolean: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readBoolean()); return arr; }, readPackedFloat: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFloat()); return arr; }, readPackedDouble: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readDouble()); return arr; }, readPackedFixed32: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFixed32()); return arr; }, readPackedSFixed32: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSFixed32()); return arr; }, readPackedFixed64: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFixed64()); return arr; }, readPackedSFixed64: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSFixed64()); return arr; }, skip: function(val) { var type = val & 0x7; if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {} else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos; else if (type === Pbf.Fixed32) this.pos += 4; else if (type === Pbf.Fixed64) this.pos += 8; else throw new Error('Unimplemented type: ' + type); }, // === WRITING ================================================================= writeTag: function(tag, type) { this.writeVarint((tag << 3) | type); }, realloc: function(min) { var length = this.length || 16; while (length < this.pos + min) length *= 2; if (length !== this.length) { var buf = new Buffer(length); this.buf.copy(buf); this.buf = buf; this.length = length; } }, finish: function() { this.length = this.pos; this.pos = 0; return this.buf.slice(0, this.length); }, writeFixed32: function(val) { this.realloc(4); this.buf.writeUInt32LE(val, this.pos); this.pos += 4; }, writeSFixed32: function(val) { this.realloc(4); this.buf.writeInt32LE(val, this.pos); this.pos += 4; }, writeFixed64: function(val) { this.realloc(8); this.buf.writeInt32LE(val & -1, this.pos); this.buf.writeUInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4); this.pos += 8; }, writeSFixed64: function(val) { this.realloc(8); this.buf.writeInt32LE(val & -1, this.pos); this.buf.writeInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4); this.pos += 8; }, writeVarint: function(val) { val = +val; if (val <= 0x7f) { this.realloc(1); this.buf[this.pos++] = val; } else if (val <= 0x3fff) { this.realloc(2); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f); } else if (val <= 0x1fffff) { this.realloc(3); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 14) & 0x7f); } else if (val <= 0xfffffff) { this.realloc(4); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 14) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 21) & 0x7f); } else { var pos = this.pos; while (val >= 0x80) { this.realloc(1); this.buf[this.pos++] = (val & 0xff) | 0x80; val /= 0x80; } this.realloc(1); this.buf[this.pos++] = val | 0; if (this.pos - pos > 10) throw new Error('Given varint doesn\'t fit into 10 bytes'); } }, writeSVarint: function(val) { this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2); }, writeBoolean: function(val) { this.writeVarint(Boolean(val)); }, writeString: function(str) { str = String(str); var bytes = Buffer.byteLength(str); this.writeVarint(bytes); this.realloc(bytes); this.buf.write(str, this.pos); this.pos += bytes; }, writeFloat: function(val) { this.realloc(4); this.buf.writeFloatLE(val, this.pos); this.pos += 4; }, writeDouble: function(val) { this.realloc(8); this.buf.writeDoubleLE(val, this.pos); this.pos += 8; }, writeBytes: function(buffer) { var len = buffer.length; this.writeVarint(len); this.realloc(len); for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i]; }, writeMessage: function(tag, fn, obj) { this.writeTag(tag, Pbf.Bytes); this.pos++; // reserve 1 byte for short message length // write the message directly to the buffer and see how much was written var startPos = this.pos; fn(obj, this); var len = this.pos - startPos; var varintLen = len <= 0x7f ? 1 : len <= 0x3fff ? 2 : len <= 0x1fffff ? 3 : len <= 0xfffffff ? 4 : Math.ceil(Math.log(len) / (Math.LN2 * 7)); // if 1 byte isn't enough for encoding message length, shift the data to the right if (varintLen > 1) { this.realloc(varintLen - 1); for (var i = this.pos - 1; i >= startPos; i--) this.buf[i + varintLen - 1] = this.buf[i]; } // finally, write the message length in the reserved place and restore the position this.pos = startPos - 1; this.writeVarint(len); this.pos += len; }, writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); }, writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); }, writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); }, writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); }, writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); }, writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); }, writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); }, writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); }, writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); }, writeBytesField: function(tag, buffer) { this.writeTag(tag, Pbf.Bytes); this.writeBytes(buffer); }, writeFixed32Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeFixed32(val); }, writeSFixed32Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeSFixed32(val); }, writeFixed64Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeFixed64(val); }, writeSFixed64Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeSFixed64(val); }, writeVarintField: function(tag, val) { this.writeTag(tag, Pbf.Varint); this.writeVarint(val); }, writeSVarintField: function(tag, val) { this.writeTag(tag, Pbf.Varint); this.writeSVarint(val); }, writeStringField: function(tag, str) { this.writeTag(tag, Pbf.Bytes); this.writeString(str); }, writeFloatField: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeFloat(val); }, writeDoubleField: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeDouble(val); }, writeBooleanField: function(tag, val) { this.writeVarintField(tag, Boolean(val)); } }; function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]); } function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]); } function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]); } function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]); } function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]); } function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]); } function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); } function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]); } function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./buffer":110}],112:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, nBits = -7, i = isLE ? (nBytes - 1) : 0, d = isLE ? -1 : 1, s = buffer[offset + i] i += d e = s & ((1 << (-nBits)) - 1) s >>= (-nBits) nBits += eLen for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} m = e & ((1 << (-nBits)) - 1) e >>= (-nBits) nBits += mLen for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { e = 1 - eBias } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { m = m + Math.pow(2, mLen) e = e - eBias } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) } exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { var e, m, c, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), i = isLE ? 0 : (nBytes - 1), d = isLE ? 1 : -1, s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 value = Math.abs(value) if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0 e = eMax } else { e = Math.floor(Math.log(value) / Math.LN2) if (value * (c = Math.pow(2, -e)) < 1) { e-- c *= 2 } if (e + eBias >= 1) { value += rt / c } else { value += rt * Math.pow(2, 1 - eBias) } if (value * c >= 2) { e++ c /= 2 } if (e + eBias >= eMax) { m = 0 e = eMax } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen) e = e + eBias } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) e = 0 } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} e = (e << mLen) | m eLen += mLen for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128 } },{}],113:[function(require,module,exports){ 'use strict'; module.exports = Point; function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { clone: function() { return new Point(this.x, this.y); }, add: function(p) { return this.clone()._add(p); }, sub: function(p) { return this.clone()._sub(p); }, mult: function(k) { return this.clone()._mult(k); }, div: function(k) { return this.clone()._div(k); }, rotate: function(a) { return this.clone()._rotate(a); }, matMult: function(m) { return this.clone()._matMult(m); }, unit: function() { return this.clone()._unit(); }, perp: function() { return this.clone()._perp(); }, round: function() { return this.clone()._round(); }, mag: function() { return Math.sqrt(this.x * this.x + this.y * this.y); }, equals: function(p) { return this.x === p.x && this.y === p.y; }, dist: function(p) { return Math.sqrt(this.distSqr(p)); }, distSqr: function(p) { var dx = p.x - this.x, dy = p.y - this.y; return dx * dx + dy * dy; }, angle: function() { return Math.atan2(this.y, this.x); }, angleTo: function(b) { return Math.atan2(this.y - b.y, this.x - b.x); }, angleWith: function(b) { return this.angleWithSep(b.x, b.y); }, // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ. angleWithSep: function(x, y) { return Math.atan2( this.x * y - this.y * x, this.x * x + this.y * y); }, _matMult: function(m) { var x = m[0] * this.x + m[1] * this.y, y = m[2] * this.x + m[3] * this.y; this.x = x; this.y = y; return this; }, _add: function(p) { this.x += p.x; this.y += p.y; return this; }, _sub: function(p) { this.x -= p.x; this.y -= p.y; return this; }, _mult: function(k) { this.x *= k; this.y *= k; return this; }, _div: function(k) { this.x /= k; this.y /= k; return this; }, _unit: function() { this._div(this.mag()); return this; }, _perp: function() { var y = this.y; this.y = this.x; this.x = -y; return this; }, _rotate: function(angle) { var cos = Math.cos(angle), sin = Math.sin(angle), x = cos * this.x - sin * this.y, y = sin * this.x + cos * this.y; this.x = x; this.y = y; return this; }, _round: function() { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; } }; // constructs Point from an array if necessary Point.convert = function (a) { if (a instanceof Point) { return a; } if (Array.isArray(a)) { return new Point(a[0], a[1]); } return a; }; },{}],114:[function(require,module,exports){ /* (c) 2013, Vladimir Agafonkin RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles. https://github.com/mourner/rbush */ (function () { 'use strict'; function rbush(maxEntries, format) { // jshint newcap: false, validthis: true if (!(this instanceof rbush)) return new rbush(maxEntries, format); // max entries in a node is 9 by default; min node fill is 40% for best performance this._maxEntries = Math.max(4, maxEntries || 9); this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); if (format) { this._initFormat(format); } this.clear(); } rbush.prototype = { all: function () { return this._all(this.data, []); }, search: function (bbox) { var node = this.data, result = [], toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return result; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf) result.push(child); else if (contains(bbox, childBBox)) this._all(child, result); else nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return result; }, collides: function (bbox) { var node = this.data, toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return false; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf || contains(bbox, childBBox)) return true; nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return false; }, load: function (data) { if (!(data && data.length)) return this; if (data.length < this._minEntries) { for (var i = 0, len = data.length; i < len; i++) { this.insert(data[i]); } return this; } // recursively build the tree with the given data from stratch using OMT algorithm var node = this._build(data.slice(), 0, data.length - 1, 0); if (!this.data.children.length) { // save as is if tree is empty this.data = node; } else if (this.data.height === node.height) { // split root if trees have the same height this._splitRoot(this.data, node); } else { if (this.data.height < node.height) { // swap trees if inserted one is bigger var tmpNode = this.data; this.data = node; node = tmpNode; } // insert the small tree into the large tree at appropriate level this._insert(node, this.data.height - node.height - 1, true); } return this; }, insert: function (item) { if (item) this._insert(item, this.data.height - 1); return this; }, clear: function () { this.data = { children: [], height: 1, bbox: empty(), leaf: true }; return this; }, remove: function (item) { if (!item) return this; var node = this.data, bbox = this.toBBox(item), path = [], indexes = [], i, parent, index, goingUp; // depth-first iterative tree traversal while (node || path.length) { if (!node) { // go up node = path.pop(); parent = path[path.length - 1]; i = indexes.pop(); goingUp = true; } if (node.leaf) { // check current node index = node.children.indexOf(item); if (index !== -1) { // item found, remove the item and condense tree upwards node.children.splice(index, 1); path.push(node); this._condense(path); return this; } } if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down path.push(node); indexes.push(i); i = 0; parent = node; node = node.children[0]; } else if (parent) { // go right i++; node = parent.children[i]; goingUp = false; } else node = null; // nothing found } return this; }, toBBox: function (item) { return item; }, compareMinX: function (a, b) { return a[0] - b[0]; }, compareMinY: function (a, b) { return a[1] - b[1]; }, toJSON: function () { return this.data; }, fromJSON: function (data) { this.data = data; return this; }, _all: function (node, result) { var nodesToSearch = []; while (node) { if (node.leaf) result.push.apply(result, node.children); else nodesToSearch.push.apply(nodesToSearch, node.children); node = nodesToSearch.pop(); } return result; }, _build: function (items, left, right, height) { var N = right - left + 1, M = this._maxEntries, node; if (N <= M) { // reached leaf level; return leaf node = { children: items.slice(left, right + 1), height: 1, bbox: null, leaf: true }; calcBBox(node, this.toBBox); return node; } if (!height) { // target height of the bulk-loaded tree height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization M = Math.ceil(N / Math.pow(M, height - 1)); } // TODO eliminate recursion? node = { children: [], height: height, bbox: null }; // split the items into M mostly square tiles var N2 = Math.ceil(N / M), N1 = N2 * Math.ceil(Math.sqrt(M)), i, j, right2, right3; multiSelect(items, left, right, N1, this.compareMinX); for (i = left; i <= right; i += N1) { right2 = Math.min(i + N1 - 1, right); multiSelect(items, i, right2, N2, this.compareMinY); for (j = i; j <= right2; j += N2) { right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively node.children.push(this._build(items, j, right3, height - 1)); } } calcBBox(node, this.toBBox); return node; }, _chooseSubtree: function (bbox, node, level, path) { var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; while (true) { path.push(node); if (node.leaf || path.length - 1 === level) break; minArea = minEnlargement = Infinity; for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; area = bboxArea(child.bbox); enlargement = enlargedArea(bbox, child.bbox) - area; // choose entry with the least area enlargement if (enlargement < minEnlargement) { minEnlargement = enlargement; minArea = area < minArea ? area : minArea; targetNode = child; } else if (enlargement === minEnlargement) { // otherwise choose one with the smallest area if (area < minArea) { minArea = area; targetNode = child; } } } node = targetNode; } return node; }, _insert: function (item, level, isNode) { var toBBox = this.toBBox, bbox = isNode ? item.bbox : toBBox(item), insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node node.children.push(item); extend(node.bbox, bbox); // split on node overflow; propagate upwards if necessary while (level >= 0) { if (insertPath[level].children.length > this._maxEntries) { this._split(insertPath, level); level--; } else break; } // adjust bboxes along the insertion path this._adjustParentBBoxes(bbox, insertPath, level); }, // split overflowed node into two _split: function (insertPath, level) { var node = insertPath[level], M = node.children.length, m = this._minEntries; this._chooseSplitAxis(node, m, M); var newNode = { children: node.children.splice(this._chooseSplitIndex(node, m, M)), height: node.height }; if (node.leaf) newNode.leaf = true; calcBBox(node, this.toBBox); calcBBox(newNode, this.toBBox); if (level) insertPath[level - 1].children.push(newNode); else this._splitRoot(node, newNode); }, _splitRoot: function (node, newNode) { // split root node this.data = { children: [node, newNode], height: node.height + 1 }; calcBBox(this.data, this.toBBox); }, _chooseSplitIndex: function (node, m, M) { var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; minOverlap = minArea = Infinity; for (i = m; i <= M - m; i++) { bbox1 = distBBox(node, 0, i, this.toBBox); bbox2 = distBBox(node, i, M, this.toBBox); overlap = intersectionArea(bbox1, bbox2); area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap if (overlap < minOverlap) { minOverlap = overlap; index = i; minArea = area < minArea ? area : minArea; } else if (overlap === minOverlap) { // otherwise choose distribution with minimum area if (area < minArea) { minArea = area; index = i; } } } return index; }, // sorts node children by the best axis for split _chooseSplitAxis: function (node, m, M) { var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, xMargin = this._allDistMargin(node, m, M, compareMinX), yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX, // otherwise it's already sorted by minY if (xMargin < yMargin) node.children.sort(compareMinX); }, // total margin of all possible split distributions where each node is at least m full _allDistMargin: function (node, m, M, compare) { node.children.sort(compare); var toBBox = this.toBBox, leftBBox = distBBox(node, 0, m, toBBox), rightBBox = distBBox(node, M - m, M, toBBox), margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), i, child; for (i = m; i < M - m; i++) { child = node.children[i]; extend(leftBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(leftBBox); } for (i = M - m - 1; i >= m; i--) { child = node.children[i]; extend(rightBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(rightBBox); } return margin; }, _adjustParentBBoxes: function (bbox, path, level) { // adjust bboxes along the given tree path for (var i = level; i >= 0; i--) { extend(path[i].bbox, bbox); } }, _condense: function (path) { // go through the path, removing empty nodes and updating bboxes for (var i = path.length - 1, siblings; i >= 0; i--) { if (path[i].children.length === 0) { if (i > 0) { siblings = path[i - 1].children; siblings.splice(siblings.indexOf(path[i]), 1); } else this.clear(); } else calcBBox(path[i], this.toBBox); } }, _initFormat: function (format) { // data format (minX, minY, maxX, maxY accessors) // uses eval-type function compilation instead of just accepting a toBBox function // because the algorithms are very sensitive to sorting functions performance, // so they should be dead simple and without inner calls // jshint evil: true var compareArr = ['return a', ' - b', ';']; this.compareMinX = new Function('a', 'b', compareArr.join(format[0])); this.compareMinY = new Function('a', 'b', compareArr.join(format[1])); this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];'); } }; // calculate node's bbox from bboxes of its children function calcBBox(node, toBBox) { node.bbox = distBBox(node, 0, node.children.length, toBBox); } // min bounding rectangle of node children from k to p-1 function distBBox(node, k, p, toBBox) { var bbox = empty(); for (var i = k, child; i < p; i++) { child = node.children[i]; extend(bbox, node.leaf ? toBBox(child) : child.bbox); } return bbox; } function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; } function extend(a, b) { a[0] = Math.min(a[0], b[0]); a[1] = Math.min(a[1], b[1]); a[2] = Math.max(a[2], b[2]); a[3] = Math.max(a[3], b[3]); return a; } function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; } function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; } function bboxArea(a) { return (a[2] - a[0]) * (a[3] - a[1]); } function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); } function enlargedArea(a, b) { return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) * (Math.max(b[3], a[3]) - Math.min(b[1], a[1])); } function intersectionArea(a, b) { var minX = Math.max(a[0], b[0]), minY = Math.max(a[1], b[1]), maxX = Math.min(a[2], b[2]), maxY = Math.min(a[3], b[3]); return Math.max(0, maxX - minX) * Math.max(0, maxY - minY); } function contains(a, b) { return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3]; } function intersects(a, b) { return b[0] <= a[2] && b[1] <= a[3] && b[2] >= a[0] && b[3] >= a[1]; } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other; // combines selection algorithm with binary divide & conquer approach function multiSelect(arr, left, right, n, compare) { var stack = [left, right], mid; while (stack.length) { right = stack.pop(); left = stack.pop(); if (right - left <= n) continue; mid = left + Math.ceil((right - left) / n / 2) * n; select(arr, left, right, mid, compare); stack.push(left, mid, mid, right); } } // Floyd-Rivest selection algorithm: // sort an array between left and right (inclusive) so that the smallest k elements come first (unordered) function select(arr, left, right, k, compare) { var n, i, z, s, sd, newLeft, newRight, t, j; while (right > left) { if (right - left > 600) { n = right - left + 1; i = k - left + 1; z = Math.log(n); s = 0.5 * Math.exp(2 * z / 3); sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1); newLeft = Math.max(left, Math.floor(k - i * s / n + sd)); newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd)); select(arr, newLeft, newRight, k, compare); } t = arr[k]; i = left; j = right; swap(arr, left, k); if (compare(arr[right], t) > 0) swap(arr, left, right); while (i < j) { swap(arr, i, j); i++; j--; while (compare(arr[i], t) < 0) i++; while (compare(arr[j], t) > 0) j--; } if (compare(arr[left], t) === 0) swap(arr, left, j); else { j++; swap(arr, j, right); } if (j <= k) left = j + 1; if (k <= j) right = j - 1; } } function swap(arr, i, j) { var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } // export as AMD/CommonJS module or global variable if (typeof define === 'function' && define.amd) define('rbush', function() { return rbush; }); else if (typeof module !== 'undefined') module.exports = rbush; else if (typeof self !== 'undefined') self.rbush = rbush; else window.rbush = rbush; })(); },{}],115:[function(require,module,exports){ // Copyright 2014 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) void (function(root, factory) { if (typeof define === "function" && define.amd) { define(factory) } else if (typeof exports === "object") { module.exports = factory() } else { root.resolveUrl = factory() } }(this, function() { function resolveUrl(/* ...urls */) { var numUrls = arguments.length if (numUrls === 0) { throw new Error("resolveUrl requires at least one argument; got none.") } var base = document.createElement("base") base.href = arguments[0] if (numUrls === 1) { return base.href } var head = document.getElementsByTagName("head")[0] head.insertBefore(base, head.firstChild) var a = document.createElement("a") var resolved for (var index = 1; index < numUrls; index++) { a.href = arguments[index] resolved = a.href base.href = resolved } head.removeChild(base) return resolved } return resolveUrl })); },{}],116:[function(require,module,exports){ /* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Ported from Webkit * http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h */ module.exports = UnitBezier; function UnitBezier(p1x, p1y, p2x, p2y) { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). this.cx = 3.0 * p1x; this.bx = 3.0 * (p2x - p1x) - this.cx; this.ax = 1.0 - this.cx - this.bx; this.cy = 3.0 * p1y; this.by = 3.0 * (p2y - p1y) - this.cy; this.ay = 1.0 - this.cy - this.by; this.p1x = p1x; this.p1y = p2y; this.p2x = p2x; this.p2y = p2y; } UnitBezier.prototype.sampleCurveX = function(t) { // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. return ((this.ax * t + this.bx) * t + this.cx) * t; }; UnitBezier.prototype.sampleCurveY = function(t) { return ((this.ay * t + this.by) * t + this.cy) * t; }; UnitBezier.prototype.sampleCurveDerivativeX = function(t) { return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx; }; UnitBezier.prototype.solveCurveX = function(x, epsilon) { if (typeof epsilon === 'undefined') epsilon = 1e-6; var t0, t1, t2, x2, i; // First try a few iterations of Newton's method -- normally very fast. for (t2 = x, i = 0; i < 8; i++) { x2 = this.sampleCurveX(t2) - x; if (Math.abs(x2) < epsilon) return t2; var d2 = this.sampleCurveDerivativeX(t2); if (Math.abs(d2) < 1e-6) break; t2 = t2 - x2 / d2; } // Fall back to the bisection method for reliability. t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) return t0; if (t2 > t1) return t1; while (t0 < t1) { x2 = this.sampleCurveX(t2); if (Math.abs(x2 - x) < epsilon) return t2; if (x > x2) { t0 = t2; } else { t1 = t2; } t2 = (t1 - t0) * 0.5 + t0; } // Failure. return t2; }; UnitBezier.prototype.solve = function(x, epsilon) { return this.sampleCurveY(this.solveCurveX(x, epsilon)); }; },{}],117:[function(require,module,exports){ module.exports.VectorTile = require('./lib/vectortile.js'); module.exports.VectorTileFeature = require('./lib/vectortilefeature.js'); module.exports.VectorTileLayer = require('./lib/vectortilelayer.js'); },{"./lib/vectortile.js":118,"./lib/vectortilefeature.js":119,"./lib/vectortilelayer.js":120}],118:[function(require,module,exports){ 'use strict'; var VectorTileLayer = require('./vectortilelayer'); module.exports = VectorTile; function VectorTile(pbf, end) { this.layers = pbf.readFields(readTile, {}, end); } function readTile(tag, layers, pbf) { if (tag === 3) { var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos); if (layer.length) layers[layer.name] = layer; } } },{"./vectortilelayer":120}],119:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = VectorTileFeature; function VectorTileFeature(pbf, end, extent, keys, values) { // Public this.properties = {}; this.extent = extent; this.type = 0; // Private this._pbf = pbf; this._geometry = -1; this._keys = keys; this._values = values; pbf.readFields(readFeature, this, end); } function readFeature(tag, feature, pbf) { if (tag == 1) feature._id = pbf.readVarint(); else if (tag == 2) readTag(pbf, feature); else if (tag == 3) feature.type = pbf.readVarint(); else if (tag == 4) feature._geometry = pbf.pos; } function readTag(pbf, feature) { var end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { var key = feature._keys[pbf.readVarint()], value = feature._values[pbf.readVarint()]; feature.properties[key] = value; } } VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon']; VectorTileFeature.prototype.loadGeometry = function() { var pbf = this._pbf; pbf.pos = this._geometry; var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, lines = [], line; while (pbf.pos < end) { if (!length) { var cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (cmd === 1) { // moveTo if (line) lines.push(line); line = []; } line.push(new Point(x, y)); } else if (cmd === 7) { line.push(line[0].clone()); // closePolygon } else { throw new Error('unknown command ' + cmd); } } if (line) lines.push(line); return lines; }; VectorTileFeature.prototype.bbox = function() { var pbf = this._pbf; pbf.pos = this._geometry; var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity; while (pbf.pos < end) { if (!length) { var cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (x < x1) x1 = x; if (x > x2) x2 = x; if (y < y1) y1 = y; if (y > y2) y2 = y; } else if (cmd !== 7) { throw new Error('unknown command ' + cmd); } } return [x1, y1, x2, y2]; }; VectorTileFeature.prototype.toGeoJSON = function(x, y, z) { var size = this.extent * Math.pow(2, z), x0 = this.extent * x, y0 = this.extent * y, coords = this.loadGeometry(), type = VectorTileFeature.types[this.type]; for (var i = 0; i < coords.length; i++) { var line = coords[i]; for (var j = 0; j < line.length; j++) { var p = line[j], y2 = 180 - (p.y + y0) * 360 / size; line[j] = [ (p.x + x0) * 360 / size - 180, 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90 ]; } } if (type === 'Point' && coords.length === 1) { coords = coords[0][0]; } else if (type === 'Point') { coords = coords[0]; type = 'MultiPoint'; } else if (type === 'LineString' && coords.length === 1) { coords = coords[0]; } else if (type === 'LineString') { type = 'MultiLineString'; } return { type: "Feature", geometry: { type: type, coordinates: coords }, properties: this.properties }; }; },{"point-geometry":113}],120:[function(require,module,exports){ 'use strict'; var VectorTileFeature = require('./vectortilefeature.js'); module.exports = VectorTileLayer; function VectorTileLayer(pbf, end) { // Public this.version = 1; this.name = null; this.extent = 4096; this.length = 0; // Private this._pbf = pbf; this._keys = []; this._values = []; this._features = []; pbf.readFields(readLayer, this, end); this.length = this._features.length; } function readLayer(tag, layer, pbf) { if (tag === 15) layer.version = pbf.readVarint(); else if (tag === 1) layer.name = pbf.readString(); else if (tag === 5) layer.extent = pbf.readVarint(); else if (tag === 2) layer._features.push(pbf.pos); else if (tag === 3) layer._keys.push(pbf.readString()); else if (tag === 4) layer._values.push(readValueMessage(pbf)); } function readValueMessage(pbf) { var value = null, end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { var tag = pbf.readVarint() >> 3; value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null; } return value; } // return feature `i` from this layer as a `VectorTileFeature` VectorTileLayer.prototype.feature = function(i) { if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds'); this._pbf.pos = this._features[i]; var end = this._pbf.readVarint() + this._pbf.pos; return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values); }; },{"./vectortilefeature.js":119}],121:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } },{}],122:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = setTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { currentQueue[queueIndex].run(); } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; clearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { setTimeout(drainQueue, 0); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],123:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } },{}],124:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (!isString(f)) { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': try { return JSON.stringify(args[i++]); } catch (_) { return '[Circular]'; } default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (isNull(x) || !isObject(x)) { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { // Allow for deprecating things in the process of starting up. if (isUndefined(global.process)) { return function() { return exports.deprecate(fn, msg).apply(this, arguments); }; } if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; var debugs = {}; var debugEnviron; exports.debuglog = function(set) { if (isUndefined(debugEnviron)) debugEnviron = process.env.NODE_DEBUG || ''; set = set.toUpperCase(); if (!debugs[set]) { if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { var pid = process.pid; debugs[set] = function() { var msg = exports.format.apply(exports, arguments); console.error('%s %d: %s', set, pid, msg); }; } else { debugs[set] = function() {}; } } return debugs[set]; }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && isFunction(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes, ctx); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // IE doesn't make error fields non-enumerable // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { return formatError(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } exports.isArray = isArray; function isBoolean(arg) { return typeof arg === 'boolean'; } exports.isBoolean = isBoolean; function isNull(arg) { return arg === null; } exports.isNull = isNull; function isNullOrUndefined(arg) { return arg == null; } exports.isNullOrUndefined = isNullOrUndefined; function isNumber(arg) { return typeof arg === 'number'; } exports.isNumber = isNumber; function isString(arg) { return typeof arg === 'string'; } exports.isString = isString; function isSymbol(arg) { return typeof arg === 'symbol'; } exports.isSymbol = isSymbol; function isUndefined(arg) { return arg === void 0; } exports.isUndefined = isUndefined; function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isObject(arg) { return typeof arg === 'object' && arg !== null; } exports.isObject = isObject; function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error); } exports.isError = isError; function isFunction(arg) { return typeof arg === 'function'; } exports.isFunction = isFunction; function isPrimitive(arg) { return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined'; } exports.isPrimitive = isPrimitive; exports.isBuffer = require('./support/isBuffer'); function objectToString(o) { return Object.prototype.toString.call(o); } function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } // log is just a thin wrapper to console.log that prepends a timestamp exports.log = function() { console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); }; /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = require('inherits'); exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || !isObject(add)) return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./support/isBuffer":123,"_process":122,"inherits":121}],125:[function(require,module,exports){ var bundleFn = arguments[3]; var sources = arguments[4]; var cache = arguments[5]; var stringify = JSON.stringify; module.exports = function (fn) { var keys = []; var wkey; var cacheKeys = Object.keys(cache); for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; if (cache[key].exports === fn) { wkey = key; break; } } if (!wkey) { wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var wcache = {}; for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; wcache[key] = key; } sources[wkey] = [ Function(['require','module','exports'], '(' + fn + ')(self)'), wcache ]; } var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var scache = {}; scache[wkey] = wkey; sources[skey] = [ Function(['require'],'require(' + stringify(wkey) + ')(self)'), scache ]; var src = '(' + bundleFn + ')({' + Object.keys(sources).map(function (key) { return stringify(key) + ':[' + sources[key][0] + ',' + stringify(sources[key][1]) + ']' ; }).join(',') + '},{},[' + stringify(skey) + '])' ; var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; return new Worker(URL.createObjectURL( new Blob([src], { type: 'text/javascript' }) )); }; },{}]},{},[22])(22) }); //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyX3NldC5qcyIsImpzL2RhdGEvYnVmZmVyL2NvbGxpc2lvbl9ib3hfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2ZpbGxfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2dseXBoX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9pY29uX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9saW5lX2VsZW1lbnRfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvbGluZV92ZXJ0ZXhfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvb3V0bGluZV9lbGVtZW50c19idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci90cmlhbmdsZV9lbGVtZW50X2J1ZmZlci5qcyIsImpzL2RhdGEvY3JlYXRlX2J1Y2tldC5qcyIsImpzL2RhdGEvZWxlbWVudF9ncm91cHMuanMiLCJqcy9kYXRhL2ZlYXR1cmVfdHJlZS5qcyIsImpzL2RhdGEvZmlsbF9idWNrZXQuanMiLCJqcy9kYXRhL2xpbmVfYnVja2V0LmpzIiwianMvZGF0YS9zeW1ib2xfYnVja2V0LmpzIiwianMvZ2VvL2Nvb3JkaW5hdGUuanMiLCJqcy9nZW8vbGF0X2xuZy5qcyIsImpzL2dlby9sYXRfbG5nX2JvdW5kcy5qcyIsImpzL2dlby90cmFuc2Zvcm0uanMiLCJqcy9saWIvZGVidWd0ZXh0LmpzIiwianMvbWFwYm94LWdsLmpzIiwianMvcmVuZGVyL2RyYXdfYmFja2dyb3VuZC5qcyIsImpzL3JlbmRlci9kcmF3X2NvbGxpc2lvbl9kZWJ1Zy5qcyIsImpzL3JlbmRlci9kcmF3X2RlYnVnLmpzIiwianMvcmVuZGVyL2RyYXdfZmlsbC5qcyIsImpzL3JlbmRlci9kcmF3X2xpbmUuanMiLCJqcy9yZW5kZXIvZHJhd19yYXN0ZXIuanMiLCJqcy9yZW5kZXIvZHJhd19zeW1ib2wuanMiLCJqcy9yZW5kZXIvZHJhd192ZXJ0aWNlcy5qcyIsImpzL3JlbmRlci9mcmFtZV9oaXN0b3J5LmpzIiwianMvcmVuZGVyL2dsX3V0aWwuanMiLCJqcy9yZW5kZXIvbGluZV9hdGxhcy5qcyIsImpzL3JlbmRlci9wYWludGVyLmpzIiwianMvcmVuZGVyL3NoYWRlcnMuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl9zb3VyY2UuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl93cmFwcGVyLmpzIiwianMvc291cmNlL3Jhc3Rlcl90aWxlX3NvdXJjZS5qcyIsImpzL3NvdXJjZS9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdGlsZS5qcyIsImpzL3NvdXJjZS90aWxlX2Nvb3JkLmpzIiwianMvc291cmNlL3RpbGVfcHlyYW1pZC5qcyIsImpzL3NvdXJjZS92ZWN0b3JfdGlsZV9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdmlkZW9fc291cmNlLmpzIiwianMvc291cmNlL3dvcmtlci5qcyIsImpzL3NvdXJjZS93b3JrZXJfdGlsZS5qcyIsImpzL3N0eWxlL2FuaW1hdGlvbl9sb29wLmpzIiwianMvc3R5bGUvaW1hZ2Vfc3ByaXRlLmpzIiwianMvc3R5bGUvbGF5b3V0X3Byb3BlcnRpZXMuanMiLCJqcy9zdHlsZS9wYWludF9wcm9wZXJ0aWVzLmpzIiwianMvc3R5bGUvcmVmZXJlbmNlLmpzIiwianMvc3R5bGUvc3R5bGUuanMiLCJqcy9zdHlsZS9zdHlsZV9jb25zdGFudC5qcyIsImpzL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uLmpzIiwianMvc3R5bGUvc3R5bGVfZGVjbGFyYXRpb25fc2V0LmpzIiwianMvc3R5bGUvc3R5bGVfbGF5ZXIuanMiLCJqcy9zdHlsZS9zdHlsZV90cmFuc2l0aW9uLmpzIiwianMvc3ltYm9sL2FuY2hvci5qcyIsImpzL3N5bWJvbC9iaW5fcGFjay5qcyIsImpzL3N5bWJvbC9jaGVja19tYXhfYW5nbGUuanMiLCJqcy9zeW1ib2wvY2xpcF9saW5lLmpzIiwianMvc3ltYm9sL2NvbGxpc2lvbl9ib3guanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX2ZlYXR1cmUuanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX3RpbGUuanMiLCJqcy9zeW1ib2wvZ2V0X2FuY2hvcnMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfYXRsYXMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfc291cmNlLmpzIiwianMvc3ltYm9sL21lcmdlbGluZXMuanMiLCJqcy9zeW1ib2wvcXVhZHMuanMiLCJqcy9zeW1ib2wvcmVzb2x2ZV9pY29ucy5qcyIsImpzL3N5bWJvbC9yZXNvbHZlX3RleHQuanMiLCJqcy9zeW1ib2wvc2hhcGluZy5qcyIsImpzL3N5bWJvbC9zcHJpdGVfYXRsYXMuanMiLCJqcy91aS9jYW1lcmEuanMiLCJqcy91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzIiwianMvdWkvY29udHJvbC9jb250cm9sLmpzIiwianMvdWkvY29udHJvbC9uYXZpZ2F0aW9uLmpzIiwianMvdWkvaGFuZGxlcnMuanMiLCJqcy91aS9oYXNoLmpzIiwianMvdWkvaW50ZXJhY3Rpb24uanMiLCJqcy91aS9tYXAuanMiLCJqcy91aS9wb3B1cC5qcyIsImpzL3V0aWwvYWN0b3IuanMiLCJqcy91dGlsL2Jyb3dzZXIvYWpheC5qcyIsImpzL3V0aWwvYnJvd3Nlci9icm93c2VyLmpzIiwianMvdXRpbC9icm93c2VyL2NhbnZhcy5qcyIsImpzL3V0aWwvYnJvd3Nlci9kaXNwYXRjaGVyLmpzIiwianMvdXRpbC9icm93c2VyL2RvbS5qcyIsImpzL3V0aWwvY29uZmlnLmpzIiwianMvdXRpbC9ldmVudGVkLmpzIiwianMvdXRpbC9nbHlwaHMuanMiLCJqcy91dGlsL2ludGVycG9sYXRlLmpzIiwianMvdXRpbC9tYXBib3guanMiLCJqcy91dGlsL21ydV9jYWNoZS5qcyIsImpzL3V0aWwvdG9rZW4uanMiLCJqcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvY3NzY29sb3JwYXJzZXIvY3NzY29sb3JwYXJzZXIuanMiLCJub2RlX21vZHVsZXMvZmVhdHVyZS1maWx0ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2VvanNvbi12dC9zcmMvY2xpcC5qcyIsIm5vZGVfbW9kdWxlcy9nZW9qc29uLXZ0L3NyYy9jb252ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3NpbXBsaWZ5LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3RpbGUuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0cml4L2Rpc3QvZ2wtbWF0cml4LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1mdW5jdGlvbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9saWIvdmFsaWRhdGUvbGF0ZXN0LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1zdHlsZS1zcGVjL2xpYi92YWxpZGF0ZS9wYXJzZWQuanMiLCJub2RlX21vZHVsZXMvbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9yZWZlcmVuY2UvdjcuanNvbiIsIm5vZGVfbW9kdWxlcy9wYmYvYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3BiZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYmYvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcG9pbnQtZ2VvbWV0cnkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmJ1c2gvcmJ1c2guanMiLCJub2RlX21vZHVsZXMvcmVzb2x2ZS11cmwvcmVzb2x2ZS11cmwuanMiLCJub2RlX21vZHVsZXMvdW5pdGJlemllci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZS5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZWZlYXR1cmUuanMiLCJub2RlX21vZHVsZXMvdmVjdG9yLXRpbGUvbGliL3ZlY3RvcnRpbGVsYXllci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvd2Vid29ya2lmeS9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzb0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxdUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9UQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4cElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQy9KQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzFrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIndXNlIHN0cmljdCc7XG5cbi8vIGEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIGEgc2luZ2xlIGFycmF5YnVmZmVyXG5cbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyO1xuXG5mdW5jdGlvbiBCdWZmZXIoYnVmZmVyKSB7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgdGhpcy5hcnJheSA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmRlZmF1bHRMZW5ndGgpO1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGVmYXVsdExlbmd0aDtcbiAgICAgICAgdGhpcy5zZXR1cFZpZXdzKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBvbmx5IHJlY3JlYXRlIGJ1ZmZlcnMgYWZ0ZXIgcmVjZWl2aW5nIHRoZW0gZnJvbSB3b3JrZXJzIGZvciBiaW5kaW5nIHRvIGdsLFxuICAgICAgICAvLyBzbyB3ZSBvbmx5IG5lZWQgdGhlc2UgMiBwcm9wZXJ0aWVzXG4gICAgICAgIHRoaXMuYXJyYXkgPSBidWZmZXIuYXJyYXk7XG4gICAgICAgIHRoaXMucG9zID0gYnVmZmVyLnBvcztcbiAgICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUgPSB7XG4gICAgcG9zOiAwLFxuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBpbiBvbmUgaXRlbVxuICAgIGRlZmF1bHRMZW5ndGg6IDgxOTIsIC8vIGluaXRpYWwgYnVmZmVyIHNpemVcbiAgICBhcnJheVR5cGU6ICdBUlJBWV9CVUZGRVInLCAvLyBnbCBidWZmZXIgdHlwZVxuXG4gICAgZ2V0IGluZGV4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3MgLyB0aGlzLml0ZW1TaXplO1xuICAgIH0sXG5cbiAgICBzZXR1cFZpZXdzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gc2V0IHVwIHZpZXdzIGZvciBlYWNoIHR5cGUgdG8gYWRkIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzIHRvIHRoZSBzYW1lIGJ1ZmZlclxuICAgICAgICB0aGlzLnVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLmJ5dGVzID0gbmV3IEludDhBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy51c2hvcnRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLnNob3J0cyA9IG5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgIH0sXG5cbiAgICAvLyBiaW5kcyB0aGUgYnVmZmVyIHRvIGEgd2ViZ2wgY29udGV4dFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsKSB7XG4gICAgICAgIHZhciB0eXBlID0gZ2xbdGhpcy5hcnJheVR5cGVdO1xuICAgICAgICBpZiAoIXRoaXMuYnVmZmVyKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wuYmluZEJ1ZmZlcih0eXBlLCB0aGlzLmJ1ZmZlcik7XG4gICAgICAgICAgICBnbC5idWZmZXJEYXRhKHR5cGUsIHRoaXMuYXJyYXkuc2xpY2UoMCwgdGhpcy5wb3MpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgICAgIC8vIGR1bXAgYXJyYXkgYnVmZmVyIG9uY2UgaXQncyBib3VuZCB0byBnbFxuICAgICAgICAgICAgdGhpcy5hcnJheSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC5iaW5kQnVmZmVyKHR5cGUsIHRoaXMuYnVmZmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBkZXN0cm95OiBmdW5jdGlvbihnbCkge1xuICAgICAgICBpZiAodGhpcy5idWZmZXIpIHtcbiAgICAgICAgICAgIGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gaW5jcmVhc2UgdGhlIGJ1ZmZlciBzaXplIGJ5IDUwJSBpZiBhIG5ldyBpdGVtIGRvZXNuJ3QgZml0XG4gICAgcmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoIDwgdGhpcy5wb3MgKyB0aGlzLml0ZW1TaXplKSB7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmxlbmd0aCA8IHRoaXMucG9zICsgdGhpcy5pdGVtU2l6ZSkge1xuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBsZW5ndGggYnkgNTAlIGJ1dCBrZWVwIGl0IGV2ZW5cbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IE1hdGgucm91bmQodGhpcy5sZW5ndGggKiAxLjUgLyAyKSAqIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGFycmF5IGJ1ZmZlcnMgY2FuJ3QgYmUgcmVzaXplZCwgc28gd2UgY3JlYXRlIGEgbmV3IG9uZSBhbmQgcmVzZXQgYWxsIGJ5dGVzIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5QnVmZmVyKHRoaXMubGVuZ3RoKTtcblxuICAgICAgICAgICAgdmFyIHVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICAgICAgdWJ5dGVzLnNldCh0aGlzLnVieXRlcyk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExpbmVWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2xpbmVfdmVydGV4X2J1ZmZlcicpO1xudmFyIExpbmVFbGVtZW50QnVmZmVyID0gcmVxdWlyZSgnLi9saW5lX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgRmlsbFZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vZmlsbF92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgRmlsbEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgT3V0bGluZUVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL291dGxpbmVfZWxlbWVudHNfYnVmZmVyJyk7XG52YXIgR2x5cGhWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2dseXBoX3ZlcnRleF9idWZmZXInKTtcbnZhciBHbHlwaEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgSWNvblZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vaWNvbl92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgSWNvbkVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9jb2xsaXNpb25fYm94X3ZlcnRleF9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihidWZmZXJzZXQpIHtcbiAgICBidWZmZXJzZXQgPSBidWZmZXJzZXQgfHwge307XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2x5cGhWZXJ0ZXg6IG5ldyBHbHlwaFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZ2x5cGhWZXJ0ZXgpLFxuICAgICAgICBnbHlwaEVsZW1lbnQ6IG5ldyBHbHlwaEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb25WZXJ0ZXg6IG5ldyBJY29uVmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5pY29uVmVydGV4KSxcbiAgICAgICAgaWNvbkVsZW1lbnQ6IG5ldyBJY29uRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQuaWNvbkVsZW1lbnQpLFxuICAgICAgICBmaWxsVmVydGV4OiBuZXcgRmlsbFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZmlsbFZlcnRleCksXG4gICAgICAgIGZpbGxFbGVtZW50OiBuZXcgRmlsbEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmZpbGxFbGVtZW50KSxcbiAgICAgICAgb3V0bGluZUVsZW1lbnQ6IG5ldyBPdXRsaW5lRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQub3V0bGluZUVsZW1lbnQpLFxuICAgICAgICBsaW5lVmVydGV4OiBuZXcgTGluZVZlcnRleEJ1ZmZlcihidWZmZXJzZXQubGluZVZlcnRleCksXG4gICAgICAgIGxpbmVFbGVtZW50OiBuZXcgTGluZUVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmxpbmVFbGVtZW50KSxcbiAgICAgICAgY29sbGlzaW9uQm94VmVydGV4OiBuZXcgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5jb2xsaXNpb25Cb3hWZXJ0ZXgpXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5Db2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiAxMiwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIGFkZDogZnVuY3Rpb24ocG9pbnQsIGV4dHJ1ZGUsIG1heFpvb20sIHBsYWNlbWVudFpvb20pIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXg7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSBwb2ludC54O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSBwb2ludC55O1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQoZXh0cnVkZS54KTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChleHRydWRlLnkpO1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSA9IE1hdGguZmxvb3IobWF4Wm9vbSAqIDEwKTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gPSBNYXRoLmZsb29yKHBsYWNlbWVudFpvb20gKiAxMCk7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gRmlsbFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogNCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ID09IDQgYnl0ZXMpXG5cbiAgICBhZGQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSB4O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSB5O1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgZGVmYXVsdExlbmd0aDogMjA0OCAqIDE2LFxuICAgIGl0ZW1TaXplOiAxNixcblxuICAgIGFkZDogZnVuY3Rpb24oeCwgeSwgb3gsIG95LCB0eCwgdHksIG1pbnpvb20sIG1heHpvb20sIGxhYmVsbWluem9vbSkge1xuICAgICAgICB2YXIgcG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICBwb3MyID0gcG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IHg7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAxXSA9IHk7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQob3ggKiA2NCk7IC8vIHVzZSAxLzY0IHBpeGVscyBmb3IgcGxhY2VtZW50XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAzXSA9IE1hdGgucm91bmQob3kgKiA2NCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMVxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSAvKiB0ZXggKi8gPSBNYXRoLmZsb29yKHR4IC8gNCk7XG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDldIC8qIHRleCAqLyA9IE1hdGguZmxvb3IodHkgLyA0KTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTBdIC8qIGxhYmVsbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKGxhYmVsbWluem9vbSkgKiAxMCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMl0gLyogbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKG1pbnpvb20pICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcblxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGExLCA0LCBnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA4KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMiwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgMTIpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2x5cGhWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIEdseXBoVmVydGV4QnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBkZWZhdWx0TGVuZ3RoOiAyMDQ4ICogMTYsXG4gICAgaXRlbVNpemU6IDE2LFxuXG4gICAgYWRkOiBmdW5jdGlvbih4LCB5LCBveCwgb3ksIHR4LCB0eSwgbWluem9vbSwgbWF4em9vbSwgbGFiZWxtaW56b29tKSB7XG4gICAgICAgIHZhciBwb3MgPSB0aGlzLnBvcyxcbiAgICAgICAgICAgIHBvczIgPSBwb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDBdID0geDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0geTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDJdID0gTWF0aC5yb3VuZChveCAqIDY0KTsgLy8gdXNlIDEvNjQgcGl4ZWxzIGZvciBwbGFjZW1lbnRcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChveSAqIDY0KTtcblxuICAgICAgICAvLyBhX2RhdGExXG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDhdIC8qIHRleCAqLyA9IHR4IC8gNDtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gLyogdGV4ICovID0gdHkgLyA0O1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMF0gLyogbGFiZWxtaW56b29tICovID0gTWF0aC5mbG9vcigobGFiZWxtaW56b29tIHx8IDApICogMTApO1xuXG4gICAgICAgIC8vIGFfZGF0YTJcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTJdIC8qIG1pbnpvb20gKi8gPSBNYXRoLmZsb29yKChtaW56b29tIHx8IDApICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSB8fCAyNSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMSwgNCwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgOCk7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YTIsIDIsIGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlLCBzdHJpZGUsIG9mZnNldCArIDEyKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVFbGVtZW50QnVmZmVyO1xuXG5mdW5jdGlvbiBMaW5lRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgaXRlbVNpemU6IDYsIC8vIGJ5dGVzIHBlciB0cmlhbmdsZSAoMyAqIHVuc2lnbmVkIHNob3J0ID09IDYgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDJdID0gYztcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZVZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gTGluZVZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG4vLyBzY2FsZSB0aGUgZXh0cnVzaW9uIHZlY3RvciBzbyB0aGF0IHRoZSBub3JtYWwgbGVuZ3RoIGlzIHRoaXMgdmFsdWUuXG4vLyBjb250YWlucyB0aGUgXCJ0ZXh0dXJlXCIgbm9ybWFscyAoLTEuLjEpLiB0aGlzIGlzIGRpc3RpbmN0IGZyb20gdGhlIGV4dHJ1ZGVcbi8vIG5vcm1hbHMgZm9yIGxpbmUgam9pbnMsIGJlY2F1c2UgdGhlIHgtdmFsdWUgcmVtYWlucyAwIGZvciB0aGUgdGV4dHVyZVxuLy8gbm9ybWFsIGFycmF5LCB3aGlsZSB0aGUgZXh0cnVkZSBub3JtYWwgYWN0dWFsbHkgbW92ZXMgdGhlIHZlcnRleCB0byBjcmVhdGVcbi8vIHRoZSBhY3V0ZS9iZXZlbGxlZCBsaW5lIGpvaW4uXG5MaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZSA9IDYzO1xuXG5MaW5lVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogOCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIC8vIHR4LCB0eSAtIHRleHR1cmUgbm9ybWFsXG4gICAgYWRkOiBmdW5jdGlvbihwb2ludCwgZXh0cnVkZSwgdHgsIHR5LCBsaW5lc29mYXIpIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXgsXG4gICAgICAgICAgICBleHRydWRlU2NhbGUgPSBMaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZTtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IChNYXRoLmZsb29yKHBvaW50LngpICogMikgfCB0eDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0gKE1hdGguZmxvb3IocG9pbnQueSkgKiAyKSB8IHR5O1xuXG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNF0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueCk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNV0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueSk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNl0gPSAobGluZXNvZmFyIHx8IDApIC8gMTI4O1xuICAgICAgICB0aGlzLmJ5dGVzW3BvcyArIDddID0gKGxpbmVzb2ZhciB8fCAwKSAlIDEyODtcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBPdXRsaW5lRWxlbWVudHNCdWZmZXI7XG5cbmZ1bmN0aW9uIE91dGxpbmVFbGVtZW50c0J1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5PdXRsaW5lRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBwZXIgbGluZSAoMiAqIHVuc2lnbmVkIHNob3J0ID09IDQgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyO1xuXG5mdW5jdGlvbiBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cblRyaWFuZ2xlRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA2LCAvLyBieXRlcyBwZXIgdHJpYW5nbGUgKDMgKiB1bnNpZ25lZCBzaG9ydCA9PSA2IGJ5dGVzKVxuICAgIGFycmF5VHlwZTogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcblxuICAgIGFkZDogZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAgICB2YXIgcG9zMiA9IHRoaXMucG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDFdID0gYjtcbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAyXSA9IGM7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCdWNrZXQ7XG5cbnZhciBMaW5lQnVja2V0ID0gcmVxdWlyZSgnLi9saW5lX2J1Y2tldCcpO1xudmFyIEZpbGxCdWNrZXQgPSByZXF1aXJlKCcuL2ZpbGxfYnVja2V0Jyk7XG52YXIgU3ltYm9sQnVja2V0ID0gcmVxdWlyZSgnLi9zeW1ib2xfYnVja2V0Jyk7XG52YXIgTGF5b3V0UHJvcGVydGllcyA9IHJlcXVpcmUoJy4uL3N0eWxlL2xheW91dF9wcm9wZXJ0aWVzJyk7XG52YXIgZmVhdHVyZUZpbHRlciA9IHJlcXVpcmUoJ2ZlYXR1cmUtZmlsdGVyJyk7XG52YXIgU3R5bGVEZWNsYXJhdGlvblNldCA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uX3NldCcpO1xuXG5mdW5jdGlvbiBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgeiwgb3ZlcnNjYWxpbmcsIGNvbGxpc2lvbkRlYnVnKSB7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBTdHlsZURlY2xhcmF0aW9uU2V0KCdsYXlvdXQnLCBsYXllci50eXBlLCBsYXllci5sYXlvdXQsIHt9KS52YWx1ZXMoKSxcbiAgICAgICAgZmFrZVpvb21IaXN0b3J5ID0geyBsYXN0SW50ZWdlclpvb206IEluZmluaXR5LCBsYXN0SW50ZWdlclpvb21UaW1lOiAwLCBsYXN0Wm9vbTogMCB9LFxuICAgICAgICBsYXlvdXQgPSB7fTtcblxuICAgIGZvciAodmFyIGsgaW4gdmFsdWVzKSB7XG4gICAgICAgIGxheW91dFtrXSA9IHZhbHVlc1trXS5jYWxjdWxhdGUoeiwgZmFrZVpvb21IaXN0b3J5KTtcbiAgICB9XG5cbiAgICB2YXIgQnVja2V0Q2xhc3MgPVxuICAgICAgICBsYXllci50eXBlID09PSAnbGluZScgPyBMaW5lQnVja2V0IDpcbiAgICAgICAgbGF5ZXIudHlwZSA9PT0gJ2ZpbGwnID8gRmlsbEJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdzeW1ib2wnID8gU3ltYm9sQnVja2V0IDogbnVsbDtcblxuICAgIHZhciBidWNrZXQgPSBuZXcgQnVja2V0Q2xhc3MoYnVmZmVycywgbmV3IExheW91dFByb3BlcnRpZXNbbGF5ZXIudHlwZV0obGF5b3V0KSwgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpO1xuXG4gICAgYnVja2V0LmlkID0gbGF5ZXIuaWQ7XG4gICAgYnVja2V0LnR5cGUgPSBsYXllci50eXBlO1xuICAgIGJ1Y2tldFsnc291cmNlLWxheWVyJ10gPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgYnVja2V0LmludGVyYWN0aXZlID0gbGF5ZXIuaW50ZXJhY3RpdmU7XG4gICAgYnVja2V0Lm1pblpvb20gPSBsYXllci5taW56b29tO1xuICAgIGJ1Y2tldC5tYXhab29tID0gbGF5ZXIubWF4em9vbTtcbiAgICBidWNrZXQuZmlsdGVyID0gZmVhdHVyZUZpbHRlcihsYXllci5maWx0ZXIpO1xuICAgIGJ1Y2tldC5mZWF0dXJlcyA9IFtdO1xuXG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBFbGVtZW50R3JvdXBzO1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXBzKHZlcnRleEJ1ZmZlciwgZWxlbWVudEJ1ZmZlciwgc2Vjb25kRWxlbWVudEJ1ZmZlcikge1xuXG4gICAgdGhpcy52ZXJ0ZXhCdWZmZXIgPSB2ZXJ0ZXhCdWZmZXI7XG4gICAgdGhpcy5lbGVtZW50QnVmZmVyID0gZWxlbWVudEJ1ZmZlcjtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRCdWZmZXIgPSBzZWNvbmRFbGVtZW50QnVmZmVyO1xuICAgIHRoaXMuZ3JvdXBzID0gW107XG59XG5cbkVsZW1lbnRHcm91cHMucHJvdG90eXBlLm1ha2VSb29tRm9yID0gZnVuY3Rpb24obnVtVmVydGljZXMpIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudCB8fCB0aGlzLmN1cnJlbnQudmVydGV4TGVuZ3RoICsgbnVtVmVydGljZXMgPiA2NTUzNSkge1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuZXcgRWxlbWVudEdyb3VwKHRoaXMudmVydGV4QnVmZmVyLmluZGV4LFxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudEJ1ZmZlciAmJiB0aGlzLmVsZW1lbnRCdWZmZXIuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRFbGVtZW50QnVmZmVyICYmIHRoaXMuc2Vjb25kRWxlbWVudEJ1ZmZlci5pbmRleCk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXAodmVydGV4U3RhcnRJbmRleCwgZWxlbWVudFN0YXJ0SW5kZXgsIHNlY29uZEVsZW1lbnRTdGFydEluZGV4KSB7XG4gICAgLy8gdGhlIG9mZnNldCBpbnRvIHRoZSB2ZXJ0ZXggYnVmZmVyIG9mIHRoZSBmaXJzdCB2ZXJ0ZXggaW4gdGhpcyBncm91cFxuICAgIHRoaXMudmVydGV4U3RhcnRJbmRleCA9IHZlcnRleFN0YXJ0SW5kZXg7XG4gICAgdGhpcy5lbGVtZW50U3RhcnRJbmRleCA9IGVsZW1lbnRTdGFydEluZGV4O1xuICAgIHRoaXMuc2Vjb25kRWxlbWVudFN0YXJ0SW5kZXggPSBzZWNvbmRFbGVtZW50U3RhcnRJbmRleDtcbiAgICB0aGlzLmVsZW1lbnRMZW5ndGggPSAwO1xuICAgIHRoaXMudmVydGV4TGVuZ3RoID0gMDtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRMZW5ndGggPSAwO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmJ1c2ggPSByZXF1aXJlKCdyYnVzaCcpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciB2dCA9IHJlcXVpcmUoJ3ZlY3Rvci10aWxlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZlYXR1cmVUcmVlO1xuXG5mdW5jdGlvbiBGZWF0dXJlVHJlZShjb29yZCwgb3ZlcnNjYWxpbmcpIHtcbiAgICB0aGlzLnggPSBjb29yZC54O1xuICAgIHRoaXMueSA9IGNvb3JkLnk7XG4gICAgdGhpcy56ID0gY29vcmQueiAtIE1hdGgubG9nKG92ZXJzY2FsaW5nKSAvIE1hdGguTE4yO1xuICAgIHRoaXMucnRyZWUgPSByYnVzaCg5KTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufVxuXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24oYmJveCwgbGF5ZXJzLCBmZWF0dXJlKSB7XG4gICAgYmJveC5sYXllcnMgPSBsYXllcnM7XG4gICAgYmJveC5mZWF0dXJlID0gZmVhdHVyZTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZC5wdXNoKGJib3gpO1xufTtcblxuLy8gYnVsayBpbnNlcnQgaW50byB0cmVlXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuX2xvYWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnJ0cmVlLmxvYWQodGhpcy50b0JlSW5zZXJ0ZWQpO1xuICAgIHRoaXMudG9CZUluc2VydGVkID0gW107XG59O1xuXG4vLyBGaW5kcyBmZWF0dXJlcyBpbiB0aGlzIHRpbGUgYXQgYSBwYXJ0aWN1bGFyIHBvc2l0aW9uLlxuRmVhdHVyZVRyZWUucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24oYXJncywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy50b0JlSW5zZXJ0ZWQubGVuZ3RoKSB0aGlzLl9sb2FkKCk7XG5cbiAgICB2YXIgcGFyYW1zID0gYXJncy5wYXJhbXMgfHwge30sXG4gICAgICAgIHJhZGl1cyA9IChwYXJhbXMucmFkaXVzIHx8IDApICogNDA5NiAvIGFyZ3Muc2NhbGUsXG4gICAgICAgIHggPSBhcmdzLngsXG4gICAgICAgIHkgPSBhcmdzLnksXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgdmFyIG1hdGNoaW5nID0gdGhpcy5ydHJlZS5zZWFyY2goWyB4IC0gcmFkaXVzLCB5IC0gcmFkaXVzLCB4ICsgcmFkaXVzLCB5ICsgcmFkaXVzIF0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBtYXRjaGluZ1tpXS5mZWF0dXJlLFxuICAgICAgICAgICAgbGF5ZXJzID0gbWF0Y2hpbmdbaV0ubGF5ZXJzLFxuICAgICAgICAgICAgdHlwZSA9IHZ0LlZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW2ZlYXR1cmUudHlwZV07XG5cbiAgICAgICAgaWYgKHBhcmFtcy4kdHlwZSAmJiB0eXBlICE9PSBwYXJhbXMuJHR5cGUpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgaWYgKCFnZW9tZXRyeUNvbnRhaW5zUG9pbnQoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSwgdHlwZSwgbmV3IFBvaW50KHgsIHkpLCByYWRpdXMpKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIGdlb0pTT04gPSBmZWF0dXJlLnRvR2VvSlNPTih0aGlzLngsIHRoaXMueSwgdGhpcy56KTtcbiAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCBsYXllcnMubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IGxheWVyc1tsXTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5sYXllciAmJiBsYXllciAhPT0gcGFyYW1zLmxheWVyLmlkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICByZXN1bHQucHVzaCh1dGlsLmV4dGVuZCh7bGF5ZXI6IGxheWVyfSwgZ2VvSlNPTikpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0KTtcbn07XG5cbmZ1bmN0aW9uIGdlb21ldHJ5Q29udGFpbnNQb2ludChyaW5ncywgdHlwZSwgcCwgcmFkaXVzKSB7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdQb2ludCcgPyBwb2ludENvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cykgOlxuICAgICAgICAgICB0eXBlID09PSAnTGluZVN0cmluZycgPyBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6XG4gICAgICAgICAgIHR5cGUgPT09ICdQb2x5Z29uJyA/IHBvbHlDb250YWluc1BvaW50KHJpbmdzLCBwKSB8fCBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6IGZhbHNlO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTUwMTcyNS8zMzEzNzkuXG5mdW5jdGlvbiBkaXN0VG9TZWdtZW50U3F1YXJlZChwLCB2LCB3KSB7XG4gICAgdmFyIGwyID0gdi5kaXN0U3FyKHcpO1xuICAgIGlmIChsMiA9PT0gMCkgcmV0dXJuIHAuZGlzdFNxcih2KTtcbiAgICB2YXIgdCA9ICgocC54IC0gdi54KSAqICh3LnggLSB2LngpICsgKHAueSAtIHYueSkgKiAody55IC0gdi55KSkgLyBsMjtcbiAgICBpZiAodCA8IDApIHJldHVybiBwLmRpc3RTcXIodik7XG4gICAgaWYgKHQgPiAxKSByZXR1cm4gcC5kaXN0U3FyKHcpO1xuICAgIHJldHVybiBwLmRpc3RTcXIody5zdWIodikuX211bHQodCkuX2FkZCh2KSk7XG59XG5cbmZ1bmN0aW9uIGxpbmVDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAvLyBGaW5kIGxpbmUgc2VnbWVudHMgdGhhdCBoYXZlIGEgZGlzdGFuY2UgPD0gcmFkaXVzXjIgdG8gcFxuICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlLCB3ZSB0cmVhdCB0aGUgbGluZSBhcyBcImNvbnRhaW5pbmcgcG9pbnQgcFwiLlxuICAgICAgICAgICAgdmFyIHYgPSByaW5nW2ogLSAxXSwgdyA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoZGlzdFRvU2VnbWVudFNxdWFyZWQocCwgdiwgdykgPCByKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIHBvaW50IGluIHBvbHlnb24gcmF5IGNhc3RpbmcgYWxnb3JpdGhtXG5mdW5jdGlvbiBwb2x5Q29udGFpbnNQb2ludChyaW5ncywgcCkge1xuICAgIHZhciBjID0gZmFsc2UsXG4gICAgICAgIHJpbmcsIHAxLCBwMjtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgcmluZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgcmluZyA9IHJpbmdzW2tdO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHJpbmcubGVuZ3RoIC0gMTsgaSA8IHJpbmcubGVuZ3RoOyBqID0gaSsrKSB7XG4gICAgICAgICAgICBwMSA9IHJpbmdbaV07XG4gICAgICAgICAgICBwMiA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoKChwMS55ID4gcC55KSAhPT0gKHAyLnkgPiBwLnkpKSAmJiAocC54IDwgKHAyLnggLSBwMS54KSAqIChwLnkgLSBwMS55KSAvIChwMi55IC0gcDEueSkgKyBwMS54KSkge1xuICAgICAgICAgICAgICAgIGMgPSAhYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gcG9pbnRDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAocmluZ1tqXS5kaXN0U3FyKHApIDw9IHIpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbEJ1Y2tldDtcblxuZnVuY3Rpb24gRmlsbEJ1Y2tldChidWZmZXJzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmZpbGxWZXJ0ZXgsIGJ1ZmZlcnMuZmlsbEVsZW1lbnQsIGJ1ZmZlcnMub3V0bGluZUVsZW1lbnQpO1xufVxuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmZWF0dXJlcyA9IHRoaXMuZmVhdHVyZXM7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xuICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxufTtcblxuRmlsbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmFkZEZpbGwobGluZXNbaV0pO1xuICAgIH1cbn07XG5cbkZpbGxCdWNrZXQucHJvdG90eXBlLmFkZEZpbGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIGlmICh2ZXJ0aWNlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgIC8vY29uc29sZS53YXJuKCdhIGZpbGwgbXVzdCBoYXZlIGF0IGxlYXN0IHRocmVlIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiB2ZXJ0aWNlcyB3ZSdyZSBnb2luZyB0byBwcm9kdWNlIHNvIHRoYXQgd2VcbiAgICAvLyBjYW4gcmVzaXplIHRoZSBidWZmZXIgYmVmb3JlaGFuZCwgb3IgZGV0ZWN0IHdoZXRoZXIgdGhlIGN1cnJlbnQgbGluZVxuICAgIC8vIHdvbid0IGZpdCBpbnRvIHRoZSBidWZmZXIgYW55bW9yZS5cbiAgICAvLyBJbiBvcmRlciB0byBiZSBhYmxlIHRvIHVzZSB0aGUgdmVydGV4IGJ1ZmZlciBmb3IgZHJhd2luZyB0aGUgYW50aWFsaWFzZWRcbiAgICAvLyBvdXRsaW5lcywgd2Ugc2VwYXJhdGUgYWxsIHBvbHlnb24gdmVydGljZXMgd2l0aCBhIGRlZ2VuZXJhdGUgKG91dC1vZi1cbiAgICAvLyB2aWV3cGxhbmUpIHZlcnRleC5cblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG5cbiAgICAvLyBDaGVjayB3aGV0aGVyIHRoaXMgZ2VvbWV0cnkgYnVmZmVyIGNhbiBob2xkIGFsbCB0aGUgcmVxdWlyZWQgdmVydGljZXMuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLm1ha2VSb29tRm9yKGxlbiArIDEpO1xuICAgIHZhciBlbGVtZW50R3JvdXAgPSB0aGlzLmVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciBmaWxsVmVydGV4ID0gdGhpcy5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmFyIGZpbGxFbGVtZW50ID0gdGhpcy5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIHZhciBvdXRsaW5lRWxlbWVudCA9IHRoaXMuYnVmZmVycy5vdXRsaW5lRWxlbWVudDtcblxuICAgIC8vIFdlJ3JlIGdlbmVyYXRpbmcgdHJpYW5nbGUgZmFucywgc28gd2UgYWx3YXlzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IGNvb3JkaW5hdGUgaW4gdGhpcyBwb2x5Z29uLlxuICAgIHZhciBmaXJzdEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4LFxuICAgICAgICBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCwgY3VycmVudFZlcnRleDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4O1xuICAgICAgICBjdXJyZW50VmVydGV4ID0gdmVydGljZXNbaV07XG5cbiAgICAgICAgZmlsbFZlcnRleC5hZGQoY3VycmVudFZlcnRleC54LCBjdXJyZW50VmVydGV4LnkpO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoKys7XG5cbiAgICAgICAgLy8gT25seSBhZGQgdHJpYW5nbGVzIHRoYXQgaGF2ZSBkaXN0aW5jdCB2ZXJ0aWNlcy5cbiAgICAgICAgaWYgKGkgPj0gMiAmJiAoY3VycmVudFZlcnRleC54ICE9PSB2ZXJ0aWNlc1swXS54IHx8IGN1cnJlbnRWZXJ0ZXgueSAhPT0gdmVydGljZXNbMF0ueSkpIHtcbiAgICAgICAgICAgIGZpbGxFbGVtZW50LmFkZChmaXJzdEluZGV4LCBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCk7XG4gICAgICAgICAgICBlbGVtZW50R3JvdXAuZWxlbWVudExlbmd0aCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGkgPj0gMSkge1xuICAgICAgICAgICAgb3V0bGluZUVsZW1lbnQuYWRkKHByZXZJbmRleCwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cC5zZWNvbmRFbGVtZW50TGVuZ3RoKys7XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2SW5kZXggPSBjdXJyZW50SW5kZXg7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZUJ1Y2tldDtcblxuZnVuY3Rpb24gTGluZUJ1Y2tldChidWZmZXJzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmxpbmVWZXJ0ZXgsIGJ1ZmZlcnMubGluZUVsZW1lbnQpO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG59XG5cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaV07XG4gICAgICAgIHRoaXMuYWRkRmVhdHVyZShmZWF0dXJlLmxvYWRHZW9tZXRyeSgpKTtcbiAgICB9XG59O1xuXG5MaW5lQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlID0gZnVuY3Rpb24obGluZXMpIHtcbiAgICB2YXIgbGF5b3V0UHJvcGVydGllcyA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuYWRkTGluZShsaW5lc1tpXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtam9pbiddLFxuICAgICAgICAgICAgbGF5b3V0UHJvcGVydGllc1snbGluZS1jYXAnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtbWl0ZXItbGltaXQnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtcm91bmQtbGltaXQnXSk7XG4gICAgfVxufTtcblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkTGluZSA9IGZ1bmN0aW9uKHZlcnRpY2VzLCBqb2luLCBjYXAsIG1pdGVyTGltaXQsIHJvdW5kTGltaXQpIHtcblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG4gICAgLy8gSWYgdGhlIGxpbmUgaGFzIGR1cGxpY2F0ZSB2ZXJ0aWNlcyBhdCB0aGUgZW5kLCBhZGp1c3QgbGVuZ3RoIHRvIHJlbW92ZSB0aGVtLlxuICAgIHdoaWxlIChsZW4gPiAyICYmIHZlcnRpY2VzW2xlbiAtIDFdLmVxdWFscyh2ZXJ0aWNlc1tsZW4gLSAyXSkpIHtcbiAgICAgICAgbGVuLS07XG4gICAgfVxuXG4gICAgaWYgKHZlcnRpY2VzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgLy9jb25zb2xlLndhcm4oJ2EgbGluZSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoam9pbiA9PT0gJ2JldmVsJykgbWl0ZXJMaW1pdCA9IDEuMDU7XG5cbiAgICB2YXIgZmlyc3RWZXJ0ZXggPSB2ZXJ0aWNlc1swXSxcbiAgICAgICAgbGFzdFZlcnRleCA9IHZlcnRpY2VzW2xlbiAtIDFdLFxuICAgICAgICBjbG9zZWQgPSBmaXJzdFZlcnRleC5lcXVhbHMobGFzdFZlcnRleCk7XG5cbiAgICAvLyB3ZSBjb3VsZCBiZSBtb3JlIHByZWNpc2UsIGJ1dCBpdCB3b3VsZCBvbmx5IHNhdmUgYSBuZWdsaWdpYmxlIGFtb3VudCBvZiBzcGFjZVxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKiA0KTtcblxuICAgIGlmIChsZW4gPT09IDIgJiYgY2xvc2VkKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignYSBsaW5lIG1heSBub3QgaGF2ZSBjb2luY2lkZW50IHBvaW50cycpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGJlZ2luQ2FwID0gY2FwLFxuICAgICAgICBlbmRDYXAgPSBjbG9zZWQgPyAnYnV0dCcgOiBjYXAsXG4gICAgICAgIGZsaXAgPSAxLFxuICAgICAgICBkaXN0YW5jZSA9IDAsXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gdHJ1ZSxcbiAgICAgICAgY3VycmVudFZlcnRleCwgcHJldlZlcnRleCwgbmV4dFZlcnRleCwgcHJldk5vcm1hbCwgbmV4dE5vcm1hbCwgb2Zmc2V0QSwgb2Zmc2V0QjtcblxuICAgIC8vIHRoZSBsYXN0IHRocmVlIHZlcnRpY2VzIGFkZGVkXG4gICAgdGhpcy5lMSA9IHRoaXMuZTIgPSB0aGlzLmUzID0gLTE7XG5cbiAgICBpZiAoY2xvc2VkKSB7XG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tsZW4gLSAyXTtcbiAgICAgICAgbmV4dE5vcm1hbCA9IGZpcnN0VmVydGV4LnN1YihjdXJyZW50VmVydGV4KS5fdW5pdCgpLl9wZXJwKCk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgIG5leHRWZXJ0ZXggPSBjbG9zZWQgJiYgaSA9PT0gbGVuIC0gMSA/XG4gICAgICAgICAgICB2ZXJ0aWNlc1sxXSA6IC8vIGlmIHRoZSBsaW5lIGlzIGNsb3NlZCwgd2UgdHJlYXQgdGhlIGxhc3QgdmVydGV4IGxpa2UgdGhlIGZpcnN0XG4gICAgICAgICAgICB2ZXJ0aWNlc1tpICsgMV07IC8vIGp1c3QgdGhlIG5leHQgdmVydGV4XG5cbiAgICAgICAgLy8gaWYgdHdvIGNvbnNlY3V0aXZlIHZlcnRpY2VzIGV4aXN0LCBza2lwIHRoZSBjdXJyZW50IG9uZVxuICAgICAgICBpZiAobmV4dFZlcnRleCAmJiB2ZXJ0aWNlc1tpXS5lcXVhbHMobmV4dFZlcnRleCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChuZXh0Tm9ybWFsKSBwcmV2Tm9ybWFsID0gbmV4dE5vcm1hbDtcbiAgICAgICAgaWYgKGN1cnJlbnRWZXJ0ZXgpIHByZXZWZXJ0ZXggPSBjdXJyZW50VmVydGV4O1xuXG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tpXTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgaG93IGZhciBhbG9uZyB0aGUgbGluZSB0aGUgY3VycmVudFZlcnRleCBpc1xuICAgICAgICBpZiAocHJldlZlcnRleCkgZGlzdGFuY2UgKz0gY3VycmVudFZlcnRleC5kaXN0KHByZXZWZXJ0ZXgpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbm9ybWFsIHRvd2FyZHMgdGhlIG5leHQgdmVydGV4IGluIHRoaXMgbGluZS4gSW4gY2FzZVxuICAgICAgICAvLyB0aGVyZSBpcyBubyBuZXh0IHZlcnRleCwgcHJldGVuZCB0aGF0IHRoZSBsaW5lIGlzIGNvbnRpbnVpbmcgc3RyYWlnaHQsXG4gICAgICAgIC8vIG1lYW5pbmcgdGhhdCB3ZSBhcmUganVzdCB1c2luZyB0aGUgcHJldmlvdXMgbm9ybWFsLlxuICAgICAgICBuZXh0Tm9ybWFsID0gbmV4dFZlcnRleCA/IG5leHRWZXJ0ZXguc3ViKGN1cnJlbnRWZXJ0ZXgpLl91bml0KCkuX3BlcnAoKSA6IHByZXZOb3JtYWw7XG5cbiAgICAgICAgLy8gSWYgd2Ugc3RpbGwgZG9uJ3QgaGF2ZSBhIHByZXZpb3VzIG5vcm1hbCwgdGhpcyBpcyB0aGUgYmVnaW5uaW5nIG9mIGFcbiAgICAgICAgLy8gbm9uLWNsb3NlZCBsaW5lLCBzbyB3ZSdyZSBkb2luZyBhIHN0cmFpZ2h0IFwiam9pblwiLlxuICAgICAgICBwcmV2Tm9ybWFsID0gcHJldk5vcm1hbCB8fCBuZXh0Tm9ybWFsO1xuXG4gICAgICAgIC8vIERldGVybWluZSB0aGUgbm9ybWFsIG9mIHRoZSBqb2luIGV4dHJ1c2lvbi4gSXQgaXMgdGhlIGFuZ2xlIGJpc2VjdG9yXG4gICAgICAgIC8vIG9mIHRoZSBzZWdtZW50cyBiZXR3ZWVuIHRoZSBwcmV2aW91cyBsaW5lIGFuZCB0aGUgbmV4dCBsaW5lLlxuICAgICAgICB2YXIgam9pbk5vcm1hbCA9IHByZXZOb3JtYWwuYWRkKG5leHROb3JtYWwpLl91bml0KCk7XG5cbiAgICAgICAgLyogIGpvaW5Ob3JtYWwgICAgIHByZXZOb3JtYWxcbiAgICAgICAgICogICAgICAgICAgICAg4oaWICAgICAg4oaRXG4gICAgICAgICAqICAgICAgICAgICAgICAgIC5fX19fX19fXy4gcHJldlZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqIG5leHROb3JtYWwgIOKGkCAgfCAgY3VycmVudFZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqICAgICBuZXh0VmVydGV4ICFcbiAgICAgICAgICpcbiAgICAgICAgICovXG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBsZW5ndGggb2YgdGhlIG1pdGVyICh0aGUgcmF0aW8gb2YgdGhlIG1pdGVyIHRvIHRoZSB3aWR0aCkuXG4gICAgICAgIC8vIEZpbmQgdGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgbmV4dCBhbmQgam9pbiBub3JtYWxzXG4gICAgICAgIC8vIHVzaW5nIGRvdCBwcm9kdWN0LiBUaGUgaW52ZXJzZSBvZiB0aGF0IGlzIHRoZSBtaXRlciBsZW5ndGguXG4gICAgICAgIHZhciBjb3NIYWxmQW5nbGUgPSBqb2luTm9ybWFsLnggKiBuZXh0Tm9ybWFsLnggKyBqb2luTm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnk7XG4gICAgICAgIHZhciBtaXRlckxlbmd0aCA9IDEgLyBjb3NIYWxmQW5nbGU7XG5cbiAgICAgICAgLy8gVGhlIGpvaW4gaWYgYSBtaWRkbGUgdmVydGV4LCBvdGhlcndpc2UgdGhlIGNhcC5cbiAgICAgICAgdmFyIG1pZGRsZVZlcnRleCA9IHByZXZWZXJ0ZXggJiYgbmV4dFZlcnRleDtcbiAgICAgICAgdmFyIGN1cnJlbnRKb2luID0gbWlkZGxlVmVydGV4ID8gam9pbiA6IG5leHRWZXJ0ZXggPyBiZWdpbkNhcCA6IGVuZENhcDtcblxuICAgICAgICBpZiAobWlkZGxlVmVydGV4ICYmIGN1cnJlbnRKb2luID09PSAncm91bmQnICYmIG1pdGVyTGVuZ3RoIDwgcm91bmRMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInICYmIG1pdGVyTGVuZ3RoID4gbWl0ZXJMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnYmV2ZWwnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBUaGUgbWF4aW11bSBleHRydWRlIGxlbmd0aCBpcyAxMjggLyA2MyA9IDIgdGltZXMgdGhlIHdpZHRoIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICAvLyBzbyBpZiBtaXRlckxlbmd0aCA+PSAyIHdlIG5lZWQgdG8gZHJhdyBhIGRpZmZlcmVudCB0eXBlIG9mIGJldmVsIHdoZXJlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoID4gMikgY3VycmVudEpvaW4gPSAnZmxpcGJldmVsJztcblxuICAgICAgICAgICAgLy8gSWYgdGhlIG1pdGVyTGVuZ3RoIGlzIHJlYWxseSBzbWFsbCBhbmQgdGhlIGxpbmUgYmV2ZWwgd291bGRuJ3QgYmUgdmlzaWJsZSxcbiAgICAgICAgICAgIC8vIGp1c3QgZHJhdyBhIG1pdGVyIGpvaW4gdG8gc2F2ZSBhIHRyaWFuZ2xlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoIDwgbWl0ZXJMaW1pdCkgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInKSB7XG4gICAgICAgICAgICBqb2luTm9ybWFsLl9tdWx0KG1pdGVyTGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgam9pbk5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdmbGlwYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBtaXRlciBpcyB0b28gYmlnLCBmbGlwIHRoZSBkaXJlY3Rpb24gdG8gbWFrZSBhIGJldmVsZWQgam9pblxuXG4gICAgICAgICAgICBpZiAobWl0ZXJMZW5ndGggPiAxMDApIHtcbiAgICAgICAgICAgICAgICAvLyBBbG1vc3QgcGFyYWxsZWwgbGluZXNcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsID0gbmV4dE5vcm1hbC5jbG9uZSgpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBwcmV2Tm9ybWFsLnggKiBuZXh0Tm9ybWFsLnkgLSBwcmV2Tm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnggPiAwID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgIHZhciBiZXZlbExlbmd0aCA9IG1pdGVyTGVuZ3RoICogcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkubWFnKCkgLyBwcmV2Tm9ybWFsLnN1YihuZXh0Tm9ybWFsKS5tYWcoKTtcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsLl9wZXJwKCkuX211bHQoYmV2ZWxMZW5ndGggKiBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBqb2luTm9ybWFsLCAwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICBmbGlwID0gLWZsaXA7XG5cbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Sm9pbiA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgdmFyIGRpciA9IHByZXZOb3JtYWwueCAqIG5leHROb3JtYWwueSAtIHByZXZOb3JtYWwueSAqIG5leHROb3JtYWwueDtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAtTWF0aC5zcXJ0KG1pdGVyTGVuZ3RoICogbWl0ZXJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGlmIChmbGlwICogZGlyID4gMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJldmVsXG4gICAgICAgICAgICBpZiAoIXN0YXJ0T2ZMaW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCBvZmZzZXRBLCBvZmZzZXRCLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC1vZmZzZXRBLCAtb2Zmc2V0QiwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdidXR0Jykge1xuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJ1dHRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIHByZXZOb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RhcnQgbmV4dCBzZWdtZW50IHdpdGggYSBidXR0XG4gICAgICAgICAgICBpZiAobmV4dFZlcnRleCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbmV4dE5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdzcXVhcmUnKSB7XG5cbiAgICAgICAgICAgIGlmICghc3RhcnRPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAvLyBDbG9zZSBwcmV2aW91cyBzZWdtZW50IHdpdGggYSBzcXVhcmUgY2FwXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgc2VnbWVudCBpcyBkb25lLiBVbnNldCB2ZXJ0aWNlcyB0byBkaXNjb25uZWN0IHNlZ21lbnRzLlxuICAgICAgICAgICAgICAgIHRoaXMuZTEgPSB0aGlzLmUyID0gLTE7XG4gICAgICAgICAgICAgICAgZmxpcCA9IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdyb3VuZCcpIHtcblxuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBidXR0XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAwLCAwLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgcm91bmQgY2FwIG9yIGxpbmVqb2luIGF0IGVuZCBvZiBzZWdtZW50XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSBzZWdtZW50IGlzIGRvbmUuIFVuc2V0IHZlcnRpY2VzIHRvIGRpc2Nvbm5lY3Qgc2VnbWVudHMuXG4gICAgICAgICAgICAgICAgdGhpcy5lMSA9IHRoaXMuZTIgPSAtMTtcbiAgICAgICAgICAgICAgICBmbGlwID0gMTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChiZWdpbkNhcCA9PT0gJ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIC8vIEFkZCByb3VuZCBjYXAgYmVmb3JlIGZpcnN0IHNlZ21lbnRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudCB3aXRoIGEgYnV0dFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gZmFsc2U7XG4gICAgfVxuXG5cbn07XG5cbi8qKlxuICogQWRkIHR3byB2ZXJ0aWNlcyB0byB0aGUgYnVmZmVycy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3VycmVudFZlcnRleCB0aGUgbGluZSB2ZXJ0ZXggdG8gYWRkIGJ1ZmZlciB2ZXJ0aWNlcyBmb3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBmbGlwIC0xIGlmIHRoZSB2ZXJ0aWNlcyBzaG91bGQgYmUgZmxpcHBlZCwgMSBvdGhlcndpc2VcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZSB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgYmVnZ2luaW5nIG9mIHRoZSBsaW5lIHRvIHRoZSB2ZXJ0ZXhcbiAqIEBwYXJhbSB7TnVtYmVyfSBlbmRMZWZ0IGV4dHJ1ZGUgdG8gc2hpZnQgdGhlIGxlZnQgdmVydGV4IGFsb25nIHRoZSBsaW5lXG4gKiBAcGFyYW0ge051bWJlcn0gZW5kUmlnaHQgZXh0cnVkZSB0byBzaGlmdCB0aGUgbGVmdCB2ZXJ0ZXggYWxvbmcgdGhlIGxpbmVcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gcm91bmQgd2hldGhlciB0aGlzIGlzIGEgcm91bmQgY2FwXG4gKi9cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEN1cnJlbnRWZXJ0ZXggPSBmdW5jdGlvbihjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbm9ybWFsLCBlbmRMZWZ0LCBlbmRSaWdodCwgcm91bmQpIHtcbiAgICB2YXIgdHggPSByb3VuZCA/IDEgOiAwO1xuICAgIHZhciBleHRydWRlO1xuXG4gICAgdmFyIGxpbmVWZXJ0ZXggPSB0aGlzLmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2YXIgbGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMubGluZUVsZW1lbnQ7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IHRoaXMuZWxlbWVudEdyb3Vwcy5jdXJyZW50O1xuICAgIHZhciB2ZXJ0ZXhTdGFydEluZGV4ID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQudmVydGV4U3RhcnRJbmRleDtcblxuICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdChmbGlwKTtcbiAgICBpZiAoZW5kTGVmdCkgZXh0cnVkZS5fc3ViKG5vcm1hbC5wZXJwKCkuX211bHQoZW5kTGVmdCkpO1xuICAgIHRoaXMuZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMCwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICBpZiAodGhpcy5lMSA+PSAwICYmIHRoaXMuZTIgPj0gMCkge1xuICAgICAgICBsaW5lRWxlbWVudC5hZGQodGhpcy5lMSwgdGhpcy5lMiwgdGhpcy5lMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoKys7XG4gICAgfVxuICAgIHRoaXMuZTEgPSB0aGlzLmUyO1xuICAgIHRoaXMuZTIgPSB0aGlzLmUzO1xuXG4gICAgZXh0cnVkZSA9IG5vcm1hbC5tdWx0KC1mbGlwKTtcbiAgICBpZiAoZW5kUmlnaHQpIGV4dHJ1ZGUuX3N1Yihub3JtYWwucGVycCgpLl9tdWx0KGVuZFJpZ2h0KSk7XG4gICAgdGhpcy5lMyA9IGxpbmVWZXJ0ZXguYWRkKGN1cnJlbnRWZXJ0ZXgsIGV4dHJ1ZGUsIHR4LCAxLCBkaXN0YW5jZSkgLSB2ZXJ0ZXhTdGFydEluZGV4O1xuICAgIGlmICh0aGlzLmUxID49IDAgJiYgdGhpcy5lMiA+PSAwKSB7XG4gICAgICAgIGxpbmVFbGVtZW50LmFkZCh0aGlzLmUxLCB0aGlzLmUyLCB0aGlzLmUzKTtcbiAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICB9XG4gICAgdGhpcy5lMSA9IHRoaXMuZTI7XG4gICAgdGhpcy5lMiA9IHRoaXMuZTM7XG5cbiAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudF9ncm91cHMnKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG52YXIgZ2V0QW5jaG9ycyA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nZXRfYW5jaG9ycycpO1xudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG52YXIgUXVhZHMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcXVhZHMnKTtcbnZhciBTaGFwaW5nID0gcmVxdWlyZSgnLi4vc3ltYm9sL3NoYXBpbmcnKTtcbnZhciByZXNvbHZlVGV4dCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9yZXNvbHZlX3RleHQnKTtcbnZhciByZXNvbHZlSWNvbnMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcmVzb2x2ZV9pY29ucycpO1xudmFyIG1lcmdlTGluZXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvbWVyZ2VsaW5lcycpO1xudmFyIHNoYXBlVGV4dCA9IFNoYXBpbmcuc2hhcGVUZXh0O1xudmFyIHNoYXBlSWNvbiA9IFNoYXBpbmcuc2hhcGVJY29uO1xudmFyIGdldEdseXBoUXVhZHMgPSBRdWFkcy5nZXRHbHlwaFF1YWRzO1xudmFyIGdldEljb25RdWFkcyA9IFF1YWRzLmdldEljb25RdWFkcztcbnZhciBjbGlwTGluZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9jbGlwX2xpbmUnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbnZhciBDb2xsaXNpb25GZWF0dXJlID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl9mZWF0dXJlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU3ltYm9sQnVja2V0O1xuXG5mdW5jdGlvbiBTeW1ib2xCdWNrZXQoYnVmZmVycywgbGF5b3V0UHJvcGVydGllcywgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpIHtcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG4gICAgdGhpcy5jb2xsaXNpb24gPSBjb2xsaXNpb247XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IG92ZXJzY2FsaW5nO1xuICAgIHRoaXMuY29sbGlzaW9uRGVidWcgPSBjb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3ltYm9sSW5zdGFuY2VzID0gW107XG5cbn1cblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gdGhpcy50ZXh0RmVhdHVyZXM7XG5cbiAgICB2YXIgaG9yaXpvbnRhbEFsaWduID0gMC41LFxuICAgICAgICB2ZXJ0aWNhbEFsaWduID0gMC41O1xuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBjYXNlICd0b3AtcmlnaHQnOlxuICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgICAgaG9yaXpvbnRhbEFsaWduID0gMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICBjYXNlICdib3R0b20tbGVmdCc6XG4gICAgICAgICAgICBob3Jpem9udGFsQWxpZ24gPSAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgY2FzZSAnYm90dG9tLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgY2FzZSAndG9wLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDA7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIganVzdGlmeSA9IGxheW91dFsndGV4dC1qdXN0aWZ5J10gPT09ICdyaWdodCcgPyAxIDpcbiAgICAgICAgbGF5b3V0Wyd0ZXh0LWp1c3RpZnknXSA9PT0gJ2xlZnQnID8gMCA6XG4gICAgICAgIDAuNTtcblxuICAgIHZhciBvbmVFbSA9IDI0O1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gbGF5b3V0Wyd0ZXh0LWxpbmUtaGVpZ2h0J10gKiBvbmVFbTtcbiAgICB2YXIgbWF4V2lkdGggPSBsYXlvdXRbJ3N5bWJvbC1wbGFjZW1lbnQnXSAhPT0gJ2xpbmUnID8gbGF5b3V0Wyd0ZXh0LW1heC13aWR0aCddICogb25lRW0gOiAwO1xuICAgIHZhciBzcGFjaW5nID0gbGF5b3V0Wyd0ZXh0LWxldHRlci1zcGFjaW5nJ10gKiBvbmVFbTtcbiAgICB2YXIgdGV4dE9mZnNldCA9IFtsYXlvdXRbJ3RleHQtb2Zmc2V0J11bMF0gKiBvbmVFbSwgbGF5b3V0Wyd0ZXh0LW9mZnNldCddWzFdICogb25lRW1dO1xuICAgIHZhciBmb250c3RhY2sgPSBsYXlvdXRbJ3RleHQtZm9udCddO1xuXG4gICAgdmFyIGdlb21ldHJpZXMgPSBbXTtcbiAgICBmb3IgKHZhciBnID0gMDsgZyA8IGZlYXR1cmVzLmxlbmd0aDsgZysrKSB7XG4gICAgICAgIGdlb21ldHJpZXMucHVzaChmZWF0dXJlc1tnXS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgLy8gTWVyZ2UgYWRqYWNlbnQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IHRvIGltcHJvdmUgbGFiZWxsaW5nLlxuICAgICAgICAvLyBJdCdzIGJldHRlciB0byBwbGFjZSBsYWJlbHMgb24gb25lIGxvbmcgbGluZSB0aGFuIG9uIG1hbnkgc2hvcnQgc2VnbWVudHMuXG4gICAgICAgIHZhciBtZXJnZWQgPSBtZXJnZUxpbmVzKGZlYXR1cmVzLCB0ZXh0RmVhdHVyZXMsIGdlb21ldHJpZXMpO1xuXG4gICAgICAgIGdlb21ldHJpZXMgPSBtZXJnZWQuZ2VvbWV0cmllcztcbiAgICAgICAgZmVhdHVyZXMgPSBtZXJnZWQuZmVhdHVyZXM7XG4gICAgICAgIHRleHRGZWF0dXJlcyA9IG1lcmdlZC50ZXh0RmVhdHVyZXM7XG4gICAgfVxuXG4gICAgdmFyIHNoYXBlZFRleHQsIHNoYXBlZEljb247XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGlmICghZ2VvbWV0cmllc1trXSkgY29udGludWU7XG5cbiAgICAgICAgaWYgKHRleHRGZWF0dXJlc1trXSkge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IHNoYXBlVGV4dCh0ZXh0RmVhdHVyZXNba10sIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10sIG1heFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBsaW5lSGVpZ2h0LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIGp1c3RpZnksIHNwYWNpbmcsIHRleHRPZmZzZXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5b3V0WydpY29uLWltYWdlJ10pIHtcbiAgICAgICAgICAgIHZhciBpY29uTmFtZSA9IHJlc29sdmVUb2tlbnMoZmVhdHVyZXNba10ucHJvcGVydGllcywgbGF5b3V0WydpY29uLWltYWdlJ10pO1xuICAgICAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pY29uc1tpY29uTmFtZV07XG4gICAgICAgICAgICBzaGFwZWRJY29uID0gc2hhcGVJY29uKGltYWdlLCBsYXlvdXQpO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZGZJY29ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2RmSWNvbnMgPSBpbWFnZS5zZGY7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNkZkljb25zICE9PSBpbWFnZS5zZGYpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdTdHlsZSBzaGVldCB3YXJuaW5nOiBDYW5ub3QgbWl4IFNERiBhbmQgbm9uLVNERiBpY29ucyBpbiBvbmUgYnVja2V0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkSWNvbiA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hhcGVkVGV4dCB8fCBzaGFwZWRJY29uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZ2VvbWV0cmllc1trXSwgc2hhcGVkVGV4dCwgc2hhcGVkSWNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnBsYWNlRmVhdHVyZXModGhpcy5idWZmZXJzLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICB2YXIgZ2x5cGhTaXplID0gMjQ7XG5cbiAgICB2YXIgZm9udFNjYWxlID0gbGF5b3V0Wyd0ZXh0LW1heC1zaXplJ10gLyBnbHlwaFNpemUsXG4gICAgICAgIHRleHRCb3hTY2FsZSA9IGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyAqIGZvbnRTY2FsZSxcbiAgICAgICAgaWNvbkJveFNjYWxlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydpY29uLW1heC1zaXplJ10sXG4gICAgICAgIHN5bWJvbE1pbkRpc3RhbmNlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydzeW1ib2wtbWluLWRpc3RhbmNlJ10sXG4gICAgICAgIGF2b2lkRWRnZXMgPSBsYXlvdXRbJ3N5bWJvbC1hdm9pZC1lZGdlcyddLFxuICAgICAgICB0ZXh0UGFkZGluZyA9IGxheW91dFsndGV4dC1wYWRkaW5nJ10gKiBjb2xsaXNpb24udGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIGljb25QYWRkaW5nID0gbGF5b3V0WydpY29uLXBhZGRpbmcnXSAqIGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdGV4dE1heEFuZ2xlID0gbGF5b3V0Wyd0ZXh0LW1heC1hbmdsZSddIC8gMTgwICogTWF0aC5QSSxcbiAgICAgICAgdGV4dEFsb25nTGluZSA9IGxheW91dFsndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgaWNvbkFsb25nTGluZSA9IGxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICAgICAgbGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddO1xuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgbGluZXMgPSBjbGlwTGluZShsaW5lcywgMCwgMCwgNDA5NiwgNDA5Nik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYW5jaG9yIHBvaW50cyBhcm91bmQgd2hpY2ggeW91IHdhbnQgdG8gcGxhY2UgbGFiZWxzXG4gICAgICAgIHZhciBhbmNob3JzID0gbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyA/XG4gICAgICAgICAgICBnZXRBbmNob3JzKGxpbmUsIHN5bWJvbE1pbkRpc3RhbmNlLCB0ZXh0TWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgdGV4dEJveFNjYWxlLCB0aGlzLm92ZXJzY2FsaW5nKSA6XG4gICAgICAgICAgICBbIG5ldyBBbmNob3IobGluZVswXS54LCBsaW5lWzBdLnksIDApIF07XG5cbiAgICAgICAgLy8gRm9yIGVhY2ggcG90ZW50aWFsIGxhYmVsLCBjcmVhdGUgdGhlIHBsYWNlbWVudCBmZWF0dXJlcyB1c2VkIHRvIGNoZWNrIGZvciBjb2xsaXNpb25zLCBhbmQgdGhlIHF1YWRzIHVzZSBmb3IgcmVuZGVyaW5nLlxuICAgICAgICBmb3IgKHZhciBqID0gMCwgbGVuID0gYW5jaG9ycy5sZW5ndGg7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgdmFyIGFuY2hvciA9IGFuY2hvcnNbal07XG5cbiAgICAgICAgICAgIHZhciBpbnNpZGUgPSAhKGFuY2hvci54IDwgMCB8fCBhbmNob3IueCA+IDQwOTYgfHwgYW5jaG9yLnkgPCAwIHx8IGFuY2hvci55ID4gNDA5Nik7XG5cbiAgICAgICAgICAgIGlmIChhdm9pZEVkZ2VzICYmICFpbnNpZGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBOb3JtYWxseSBzeW1ib2wgbGF5ZXJzIGFyZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBPbmx5IHN5bWJvbHNcbiAgICAgICAgICAgIC8vIHdpdGggdGhlaXIgYW5jaG9ycyB3aXRoaW4gdGhlIHRpbGUgYm91bmRhcmllcyBhcmUgYWRkZWQgdG8gdGhlIGJ1ZmZlcnNcbiAgICAgICAgICAgIC8vIHRvIHByZXZlbnQgc3ltYm9scyBmcm9tIGJlaW5nIGRyYXduIHR3aWNlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFN5bWJvbHMgaW4gbGF5ZXJzIHdpdGggb3ZlcmxhcCBhcmUgc29ydGVkIGluIHRoZSB5IGRpcmVjdGlvbiBzbyB0aGF0XG4gICAgICAgICAgICAvLyBzeW1ib2xzIGxvd2VyIG9uIHRoZSBjYW52YXMgYXJlIGRyYXduIG9uIHRvcCBvZiBzeW1ib2xzIG5lYXIgdGhlIHRvcC5cbiAgICAgICAgICAgIC8vIFRvIHByZXNlcnZlIHRoaXMgb3JkZXIgYWNyb3NzIHRpbGUgYm91bmRhcmllcyB0aGVzZSBzeW1ib2xzIGNhbid0XG4gICAgICAgICAgICAvLyBiZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBJbnN0ZWFkIHRoZXkgbmVlZCB0byBiZSBpbmNsdWRlZCBpblxuICAgICAgICAgICAgLy8gdGhlIGJ1ZmZlcnMgZm9yIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgdG8gdGlsZSBib3VuZGFyaWVzIGF0IGRyYXcgdGltZS5cbiAgICAgICAgICAgIHZhciBhZGRUb0J1ZmZlcnMgPSBpbnNpZGUgfHwgbWF5T3ZlcmxhcDtcblxuICAgICAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMucHVzaChuZXcgU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLnBsYWNlRmVhdHVyZXMgPSBmdW5jdGlvbihidWZmZXJzLCBjb2xsaXNpb25EZWJ1Zykge1xuXG4gICAgLy8gQ2FsY3VsYXRlIHdoaWNoIGxhYmVscyBjYW4gYmUgc2hvd24gYW5kIHdoZW4gdGhleSBjYW4gYmUgc2hvd24gYW5kXG4gICAgLy8gY3JlYXRlIHRoZSBidWZlcnMgdXNlZCBmb3IgcmVuZGVyaW5nLlxuXG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcblxuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGhpcy5lbGVtZW50R3JvdXBzID0ge1xuICAgICAgICB0ZXh0OiBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmdseXBoVmVydGV4LCBidWZmZXJzLmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb246IG5ldyBFbGVtZW50R3JvdXBzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCksXG4gICAgICAgIHNkZkljb25zOiB0aGlzLnNkZkljb25zXG4gICAgfTtcblxuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGNvbGxpc2lvbiA9IHRoaXMuY29sbGlzaW9uO1xuICAgIHZhciBtYXhTY2FsZSA9IHRoaXMuY29sbGlzaW9uLm1heFNjYWxlO1xuXG4gICAgdmFyIHRleHRBbG9uZ0xpbmUgPSBsYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG4gICAgdmFyIGljb25BbG9uZ0xpbmUgPSBsYXlvdXRbJ2ljb24tcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG5cbiAgICB2YXIgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICBsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddIHx8IGxheW91dFsnaWNvbi1pZ25vcmUtcGxhY2VtZW50J107XG5cbiAgICAvLyBTb3J0IHN5bWJvbHMgYnkgdGhlaXIgeSBwb3NpdGlvbiBvbiB0aGUgY2FudmFzIHNvIHRoYXQgdGhleSBsb3dlciBzeW1ib2xzXG4gICAgLy8gYXJlIGRyYXduIG9uIHRvcCBvZiBoaWdoZXIgc3ltYm9scy5cbiAgICAvLyBEb24ndCBzb3J0IHN5bWJvbHMgdGhhdCB3b24ndCBvdmVybGFwIGJlY2F1c2UgaXQgaXNuJ3QgbmVjZXNzYXJ5IGFuZFxuICAgIC8vIGJlY2F1c2UgaXQgY2F1c2VzIG1vcmUgbGFiZWxzIHRvIHBvcCBpbiBhbmQgb3V0IHdoZW4gcm90YXRpbmcuXG4gICAgaWYgKG1heU92ZXJsYXApIHtcbiAgICAgICAgdmFyIGFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGU7XG4gICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICBjb3MgPSBNYXRoLmNvcyhhbmdsZSk7XG5cbiAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICB2YXIgYVJvdGF0ZWQgPSBzaW4gKiBhLnggKyBjb3MgKiBhLnk7XG4gICAgICAgICAgICB2YXIgYlJvdGF0ZWQgPSBzaW4gKiBiLnggKyBjb3MgKiBiLnk7XG4gICAgICAgICAgICByZXR1cm4gYlJvdGF0ZWQgLSBhUm90YXRlZDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgcCA9IDA7IHAgPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IHArKykge1xuICAgICAgICB2YXIgc3ltYm9sSW5zdGFuY2UgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1twXTtcbiAgICAgICAgdmFyIGhhc1RleHQgPSBzeW1ib2xJbnN0YW5jZS5oYXNUZXh0O1xuICAgICAgICB2YXIgaGFzSWNvbiA9IHN5bWJvbEluc3RhbmNlLmhhc0ljb247XG5cbiAgICAgICAgdmFyIGljb25XaXRob3V0VGV4dCA9IGxheW91dFsndGV4dC1vcHRpb25hbCddIHx8ICFoYXNUZXh0LFxuICAgICAgICAgICAgdGV4dFdpdGhvdXRJY29uID0gbGF5b3V0WydpY29uLW9wdGlvbmFsJ10gfHwgIWhhc0ljb247XG5cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNjYWxlcyBhdCB3aGljaCB0aGUgdGV4dCBhbmQgaWNvbiBjYW4gYmUgcGxhY2VkIHdpdGhvdXQgY29sbGlzaW9uLlxuXG4gICAgICAgIHZhciBnbHlwaFNjYWxlID0gaGFzVGV4dCAmJiAhbGF5b3V0Wyd0ZXh0LWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLnRleHRDb2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuICAgICAgICB2YXIgaWNvblNjYWxlID0gaGFzSWNvbiAmJiAhbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLmljb25Db2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuXG4gICAgICAgIC8vIENvbWJpbmUgdGhlIHNjYWxlcyBmb3IgaWNvbnMgYW5kIHRleHQuXG5cbiAgICAgICAgaWYgKCFpY29uV2l0aG91dFRleHQgJiYgIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gZ2x5cGhTY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRleHRXaXRob3V0SWNvbiAmJiBnbHlwaFNjYWxlKSB7XG4gICAgICAgICAgICBnbHlwaFNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfSBlbHNlIGlmICghaWNvbldpdGhvdXRUZXh0ICYmIGljb25TY2FsZSkge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgLy8gSW5zZXJ0IGZpbmFsIHBsYWNlbWVudCBpbnRvIGNvbGxpc2lvbiB0cmVlIGFuZCBhZGQgZ2x5cGhzL2ljb25zIHRvIGJ1ZmZlcnNcblxuICAgICAgICBpZiAoaGFzVGV4dCkge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UudGV4dENvbGxpc2lvbkZlYXR1cmUsIGdseXBoU2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdseXBoU2NhbGUgPD0gbWF4U2NhbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFN5bWJvbHMoYnVmZmVycy5nbHlwaFZlcnRleCwgYnVmZmVycy5nbHlwaEVsZW1lbnQsIGVsZW1lbnRHcm91cHMudGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJvbEluc3RhbmNlLmdseXBoUXVhZHMsIGdseXBoU2NhbGUsIGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXSwgdGV4dEFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzSWNvbikge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UuaWNvbkNvbGxpc2lvbkZlYXR1cmUsIGljb25TY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaWNvblNjYWxlIDw9IG1heFNjYWxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTeW1ib2xzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCwgZWxlbWVudEdyb3Vwcy5pY29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3ltYm9sSW5zdGFuY2UuaWNvblF1YWRzLCBpY29uU2NhbGUsIGxheW91dFsnaWNvbi1rZWVwLXVwcmlnaHQnXSwgaWNvbkFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGlmIChjb2xsaXNpb25EZWJ1ZykgdGhpcy5hZGRUb0RlYnVnQnVmZmVycygpO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRTeW1ib2xzID0gZnVuY3Rpb24odmVydGV4LCBlbGVtZW50LCBlbGVtZW50R3JvdXBzLCBxdWFkcywgc2NhbGUsIGtlZXBVcHJpZ2h0LCBhbG9uZ0xpbmUpIHtcblxuICAgIGVsZW1lbnRHcm91cHMubWFrZVJvb21Gb3IoNCAqIHF1YWRzLmxlbmd0aCk7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IGVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciB6b29tID0gdGhpcy5jb2xsaXNpb24uem9vbTtcbiAgICB2YXIgcGxhY2VtZW50Wm9vbSA9IE1hdGgubWF4KE1hdGgubG9nKHNjYWxlKSAvIE1hdGguTE4yICsgem9vbSwgMCk7XG4gICAgdmFyIHBsYWNlbWVudEFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGUgKyBNYXRoLlBJO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBxdWFkcy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBxdWFkc1trXSxcbiAgICAgICAgICAgIGFuZ2xlID0gc3ltYm9sLmFuZ2xlO1xuXG4gICAgICAgIC8vIGRyb3AgdXBzaWRlIGRvd24gdmVyc2lvbnMgb2YgZ2x5cGhzXG4gICAgICAgIHZhciBhID0gKGFuZ2xlICsgcGxhY2VtZW50QW5nbGUpICUgKE1hdGguUEkgKiAyKTtcbiAgICAgICAgaWYgKGtlZXBVcHJpZ2h0ICYmIGFsb25nTGluZSAmJiAoYSA8PSBNYXRoLlBJIC8gMiB8fCBhID4gTWF0aC5QSSAqIDMgLyAyKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIHRsID0gc3ltYm9sLnRsLFxuICAgICAgICAgICAgdHIgPSBzeW1ib2wudHIsXG4gICAgICAgICAgICBibCA9IHN5bWJvbC5ibCxcbiAgICAgICAgICAgIGJyID0gc3ltYm9sLmJyLFxuICAgICAgICAgICAgdGV4ID0gc3ltYm9sLnRleCxcbiAgICAgICAgICAgIGFuY2hvciA9IHN5bWJvbC5hbmNob3IsXG5cbiAgICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heCh6b29tICsgTWF0aC5sb2coc3ltYm9sLm1pblNjYWxlKSAvIE1hdGguTE4yLCBwbGFjZW1lbnRab29tKSxcbiAgICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbih6b29tICsgTWF0aC5sb2coc3ltYm9sLm1heFNjYWxlKSAvIE1hdGguTE4yLCAyNSk7XG5cbiAgICAgICAgaWYgKG1heFpvb20gPD0gbWluWm9vbSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTG93ZXIgbWluIHpvb20gc28gdGhhdCB3aGlsZSBmYWRpbmcgb3V0IHRoZSBsYWJlbCBpdCBjYW4gYmUgc2hvd24gb3V0c2lkZSBvZiBjb2xsaXNpb24tZnJlZSB6b29tIGxldmVsc1xuICAgICAgICBpZiAobWluWm9vbSA9PT0gcGxhY2VtZW50Wm9vbSkgbWluWm9vbSA9IDA7XG5cbiAgICAgICAgdmFyIHRyaWFuZ2xlSW5kZXggPSB2ZXJ0ZXguaW5kZXggLSBlbGVtZW50R3JvdXAudmVydGV4U3RhcnRJbmRleDtcblxuICAgICAgICB2ZXJ0ZXguYWRkKGFuY2hvci54LCBhbmNob3IueSwgdGwueCwgdGwueSwgdGV4LngsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRyLngsIHRyLnksIHRleC54ICsgdGV4LncsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJsLngsIGJsLnksIHRleC54LCB0ZXgueSArIHRleC5oLCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJyLngsIGJyLnksIHRleC54ICsgdGV4LncsIHRleC55ICsgdGV4LmgsIG1pblpvb20sIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDQ7XG5cbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCwgdHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyKTtcbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyLCB0cmlhbmdsZUluZGV4ICsgMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoICs9IDI7XG4gICAgfVxuXG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmaXJzdGRvbmUgPSBmYWxzZTtcbiAgICB0aGlzLmdldFRleHREZXBlbmRlbmNpZXModGlsZSwgYWN0b3IsIGRvbmUpO1xuICAgIHRoaXMuZ2V0SWNvbkRlcGVuZGVuY2llcyh0aWxlLCBhY3RvciwgZG9uZSk7XG4gICAgZnVuY3Rpb24gZG9uZShlcnIpIHtcbiAgICAgICAgaWYgKGVyciB8fCBmaXJzdGRvbmUpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICBmaXJzdGRvbmUgPSB0cnVlO1xuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuZ2V0SWNvbkRlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmxheW91dFByb3BlcnRpZXNbJ2ljb24taW1hZ2UnXSkge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgICAgICB2YXIgaWNvbnMgPSByZXNvbHZlSWNvbnMoZmVhdHVyZXMsIHRoaXMubGF5b3V0UHJvcGVydGllcyk7XG5cbiAgICAgICAgaWYgKGljb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgYWN0b3Iuc2VuZCgnZ2V0IGljb25zJywgeyBpY29uczogaWNvbnMgfSwgc2V0SWNvbnMuYmluZCh0aGlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRJY29ucyhlcnIsIG5ld2ljb25zKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB0aGlzLmljb25zID0gbmV3aWNvbnM7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5nZXRUZXh0RGVwZW5kZW5jaWVzID0gZnVuY3Rpb24odGlsZSwgYWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgZm9udHN0YWNrID0gdGhpcy5sYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZvbnQnXTtcblxuICAgIHZhciBzdGFja3MgPSB0aGlzLnN0YWNrcyA9IHRpbGUuc3RhY2tzO1xuICAgIGlmIChzdGFja3NbZm9udHN0YWNrXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN0YWNrc1tmb250c3RhY2tdID0ge307XG4gICAgfVxuICAgIHZhciBzdGFjayA9IHN0YWNrc1tmb250c3RhY2tdO1xuXG4gICAgdmFyIGRhdGEgPSByZXNvbHZlVGV4dChmZWF0dXJlcywgdGhpcy5sYXlvdXRQcm9wZXJ0aWVzLCBzdGFjayk7XG4gICAgdGhpcy50ZXh0RmVhdHVyZXMgPSBkYXRhLnRleHRGZWF0dXJlcztcblxuICAgIGFjdG9yLnNlbmQoJ2dldCBnbHlwaHMnLCB7XG4gICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgIGZvbnRzdGFjazogZm9udHN0YWNrLFxuICAgICAgICBjb2RlcG9pbnRzOiBkYXRhLmNvZGVwb2ludHNcbiAgICB9LCBmdW5jdGlvbihlcnIsIG5ld3N0YWNrKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgIGZvciAodmFyIGNvZGVwb2ludCBpbiBuZXdzdGFjaykge1xuICAgICAgICAgICAgc3RhY2tbY29kZXBvaW50XSA9IG5ld3N0YWNrW2NvZGVwb2ludF07XG4gICAgICAgIH1cblxuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRUb0RlYnVnQnVmZmVycyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveCA9IG5ldyBFbGVtZW50R3JvdXBzKHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXgpO1xuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5jb2xsaXNpb25Cb3gubWFrZVJvb21Gb3IoMCk7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIGFuZ2xlID0gLXRoaXMuY29sbGlzaW9uLmFuZ2xlO1xuICAgIHZhciB5U3RyZXRjaCA9IHRoaXMuY29sbGlzaW9uLnlTdHJldGNoO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZlYXR1cmUgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1tqXVtpID09PSAwID8gJ3RleHRDb2xsaXNpb25GZWF0dXJlJyA6ICdpY29uQ29sbGlzaW9uRmVhdHVyZSddO1xuICAgICAgICAgICAgaWYgKCFmZWF0dXJlKSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBib3hlcyA9IGZlYXR1cmUuYm94ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwOyBiIDwgYm94ZXMubGVuZ3RoOyBiKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYm94ID0gYm94ZXNbYl07XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IGJveC5hbmNob3I7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGwgPSBuZXcgUG9pbnQoYm94LngxLCBib3gueTEgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG4gICAgICAgICAgICAgICAgdmFyIHRyID0gbmV3IFBvaW50KGJveC54MiwgYm94LnkxICogeVN0cmV0Y2gpLl9yb3RhdGUoYW5nbGUpO1xuICAgICAgICAgICAgICAgIHZhciBibCA9IG5ldyBQb2ludChib3gueDEsIGJveC55MiAqIHlTdHJldGNoKS5fcm90YXRlKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICB2YXIgYnIgPSBuZXcgUG9pbnQoYm94LngyLCBib3gueTIgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4Wm9vbSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDI1LCB0aGlzLmNvbGxpc2lvbi56b29tICsgTWF0aC5sb2coYm94Lm1heFNjYWxlKSAvIE1hdGguTE4yKSk7XG4gICAgICAgICAgICAgICAgdmFyIHBsYWNlbWVudFpvb20gPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNSwgdGhpcy5jb2xsaXNpb24uem9vbSArIE1hdGgubG9nKGJveC5wbGFjZW1lbnRTY2FsZSkgLyBNYXRoLkxOMikpO1xuXG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIHRsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdHIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCB0ciwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJyLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgYnIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCBibCwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdGwsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveC5jdXJyZW50LnZlcnRleExlbmd0aCArPSA4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSB7XG5cbiAgICB0aGlzLnggPSBhbmNob3IueDtcbiAgICB0aGlzLnkgPSBhbmNob3IueTtcbiAgICB0aGlzLmhhc1RleHQgPSAhIXNoYXBlZFRleHQ7XG4gICAgdGhpcy5oYXNJY29uID0gISFzaGFwZWRJY29uO1xuXG4gICAgaWYgKHRoaXMuaGFzVGV4dCkge1xuICAgICAgICB0aGlzLmdseXBoUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRHbHlwaFF1YWRzKGFuY2hvciwgc2hhcGVkVGV4dCwgdGV4dEJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIHRleHRBbG9uZ0xpbmUpIDogW107XG4gICAgICAgIHRoaXMudGV4dENvbGxpc2lvbkZlYXR1cmUgPSBuZXcgQ29sbGlzaW9uRmVhdHVyZShsaW5lLCBhbmNob3IsIHNoYXBlZFRleHQsIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0ljb24pIHtcbiAgICAgICAgdGhpcy5pY29uUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRJY29uUXVhZHMoYW5jaG9yLCBzaGFwZWRJY29uLCBpY29uQm94U2NhbGUsIGxpbmUsIGxheW91dCwgaWNvbkFsb25nTGluZSkgOiBbXTtcbiAgICAgICAgdGhpcy5pY29uQ29sbGlzaW9uRmVhdHVyZSA9IG5ldyBDb2xsaXNpb25GZWF0dXJlKGxpbmUsIGFuY2hvciwgc2hhcGVkSWNvbiwgaWNvbkJveFNjYWxlLCBpY29uUGFkZGluZywgaWNvbkFsb25nTGluZSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvb3JkaW5hdGU7XG5cbi8qKlxuICogQSBjb29yZGluYXRlIGlzIGEgY29sdW1uLCByb3csIHpvb20gY29tYmluYXRpb24sIG9mdGVuIHVzZWRcbiAqIGFzIHRoZSBkYXRhIGNvbXBvbmVudCBvZiBhIHRpbGUuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IGNvbHVtblxuICogQHBhcmFtIHtOdW1iZXJ9IHJvd1xuICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIENvb3JkaW5hdGUoY29sdW1uLCByb3csIHpvb20pIHtcbiAgICB0aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICB0aGlzLnJvdyA9IHJvdztcbiAgICB0aGlzLnpvb20gPSB6b29tO1xufVxuXG5Db29yZGluYXRlLnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGNsb25lIG9mIHRoaXMgY29vcmRpbmF0ZSB0aGF0IGNhbiBiZSBtdXRhdGVkIHdpdGhvdXRcbiAgICAgKiBjaGFuZ2luZyB0aGUgb3JpZ2luYWwgY29vcmRpbmF0ZVxuICAgICAqXG4gICAgICogQHJldHVybnMge0Nvb3JkaW5hdGV9IGNsb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC5jbG9uZSgpO1xuICAgICAqIC8vIHNpbmNlIGNvb3JkIGlzIGNsb25lZCwgbW9kaWZ5aW5nIGEgcHJvcGVydHkgb2YgYzIgZG9lc1xuICAgICAqIC8vIG5vdCBtb2RpZnkgaXQuXG4gICAgICogYzIuem9vbSA9IDI7XG4gICAgICovXG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUodGhpcy5jb2x1bW4sIHRoaXMucm93LCB0aGlzLnpvb20pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIHRoaXMgY29vcmRpbmF0ZSB0byBhIGdpdmVuIHpvb20gbGV2ZWwuIFRoaXMgcmV0dXJucyBhIG5ld1xuICAgICAqIGNvb3JkaW5hdGUgb2JqZWN0LCBub3QgbXV0YXRpbmcgdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gem9vbVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSB6b29tZWQgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC56b29tVG8oMSk7XG4gICAgICogYzIgLy8gZXF1YWxzIG5ldyBDb29yZGluYXRlKDAsIDAsIDEpO1xuICAgICAqL1xuICAgIHpvb21UbzogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl96b29tVG8oem9vbSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTdWJ0cmFjdCB0aGUgY29sdW1uIGFuZCByb3cgdmFsdWVzIG9mIHRoaXMgY29vcmRpbmF0ZSBmcm9tIHRob3NlXG4gICAgICogb2YgYW5vdGhlciBjb29yZGluYXRlLiBUaGUgb3RoZXIgY29vcmRpbmF0IHdpbGwgYmUgem9vbWVkIHRvIHRoZVxuICAgICAqIHNhbWUgbGV2ZWwgYXMgYHRoaXNgIGJlZm9yZSB0aGUgc3VidHJhY3Rpb24gb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGMgb3RoZXIgY29vcmRpbmF0ZVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSByZXN1bHRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN1YjogZnVuY3Rpb24oYykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWIoYyk7IH0sXG5cbiAgICBfem9vbVRvOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHZhciBzY2FsZSA9IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAqPSBzY2FsZTtcbiAgICAgICAgdGhpcy5yb3cgKj0gc2NhbGU7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfc3ViOiBmdW5jdGlvbihjKSB7XG4gICAgICAgIGMgPSBjLnpvb21Ubyh0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAtPSBjLmNvbHVtbjtcbiAgICAgICAgdGhpcy5yb3cgLT0gYy5yb3c7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nO1xuXG52YXIgd3JhcCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpLndyYXA7XG5cbi8qKlxuICogQ3JlYXRlIGEgbGF0aXR1ZGUsIGxvbmdpdHVkZSBvYmplY3QgZnJvbSBhIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcGFpciBpbiBkZWdyZWVzLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiBhIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcG9pbnQsIGluIGRlZ3JlZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gbGF0IGxhdGl0dWRlXG4gKiBAcGFyYW0ge251bWJlcn0gbG5nIGxvbmdpdHVkZVxuICogQGV4YW1wbGVcbiAqIHZhciBsYXRsbmcgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDM3Ljc2LCAtMTIyLjQ0KTtcbiAqL1xuZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nKSB7XG4gICAgaWYgKGlzTmFOKGxhdCkgfHwgaXNOYU4obG5nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgTGF0TG5nIG9iamVjdDogKCcgKyBsYXQgKyAnLCAnICsgbG5nICsgJyknKTtcbiAgICB9XG4gICAgdGhpcy5sYXQgPSArbGF0O1xuICAgIHRoaXMubG5nID0gK2xuZztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBuZXcgYExhdExuZ2Agb2JqZWN0IHdob3NlIGxvbmdpdHVkZSBpcyB3cmFwcGVkIHRvIHRoZSByYW5nZSAoLTE4MCwgMTgwKS5cbiAqXG4gKiBAcmV0dXJucyB7TGF0TG5nfSB3cmFwcGVkIExhdExuZyBvYmplY3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9pbnQgPSBtYXBib3hnbC5MYXRMbmcoMCwgMjAwKTtcbiAqIHZhciB3cmFwcGVkID0gcG9pbnQud3JhcCgpO1xuICogd3JhcHBlZC5sbmc7IC8vID0gLTE2MFxuICovXG5MYXRMbmcucHJvdG90eXBlLndyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHdyYXAodGhpcy5sbmcsIC0xODAsIDE4MCkpO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IGFuIGFycmF5IHRvIGEgYExhdExuZ2Agb2JqZWN0LCBvciByZXR1cm4gYW4gZXhpc3RpbmcgYExhdExuZ2Agb2JqZWN0XG4gKiB1bmNoYW5nZWQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fExhdExuZ30gaW5wdXQgYGlucHV0YCB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7TGF0TG5nfSBMYXRMbmcgb2JqZWN0IG9yIG9yaWdpbmFsIGlucHV0XG4gKiBAZXhhbXBsZVxuICogdmFyIGxsID0gbWFwYm94Z2wuTGF0TG5nLmNvbnZlcnQoWzEwLCAxMF0pO1xuICogdmFyIGxsMiA9IG5ldyBtYXBib3hnbC5MYXRMbmcoMTAsIDEwKTtcbiAqIGxsIC8vID0gbGwyXG4gKi9cbkxhdExuZy5jb252ZXJ0ID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKGlucHV0WzBdLCBpbnB1dFsxXSk7XG4gICAgfVxuICAgIHJldHVybiBpbnB1dDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nQm91bmRzO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJvdW5kaW5nIGJveCBmcm9tIHRoZSBnaXZlbiBwYWlyIG9mIHBvaW50cy4gSWYgcGFyYW1ldGVyZXMgYXJlIG9taXR0ZWQsIGEgYG51bGxgIGJvdW5kaW5nIGJveCBpcyBjcmVhdGVkLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdCb3VuZHNcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiByZWN0YW5ndWxhciBib3ggb24gdGhlIGVhcnRoLCBkZWZpbmVkIGJ5IGl0cyBzb3V0aHdlc3QgYW5kIG5vcnRoZWFzdCBwb2ludHMgaW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS5cbiAqIEBwYXJhbSB7TGF0TG5nfSBzdyBzb3V0aHdlc3RcbiAqIEBwYXJhbSB7TGF0TG5nfSBuZSBub3J0aGVhc3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgc3cgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDAsIDApO1xuICogdmFyIG5lID0gbmV3IG1hcGJveGdsLkxhdExuZygxMCwgLTEwKTtcbiAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKHN3LCBuZSk7XG4gKlxuICovXG5mdW5jdGlvbiBMYXRMbmdCb3VuZHMoc3csIG5lKSB7XG4gICAgaWYgKCFzdykgcmV0dXJuO1xuXG4gICAgdmFyIGxhdGxuZ3MgPSBuZSA/IFtzdywgbmVdIDogc3c7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB0aGlzLmV4dGVuZChsYXRsbmdzW2ldKTtcbiAgICB9XG59XG5cbkxhdExuZ0JvdW5kcy5wcm90b3R5cGUgPSB7XG5cbiAgICAvKipcbiAgICAgKiBFeHRlbmQgdGhlIGJvdW5kcyB0byBpbmNsdWRlIGEgZ2l2ZW4gTGF0TG5nIG9yIExhdExuZ0JvdW5kcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TGF0TG5nfExhdExuZ0JvdW5kc30gb2JqIG9iamVjdCB0byBleHRlbmQgdG9cbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nQm91bmRzfSBgdGhpc2BcbiAgICAgKi9cbiAgICBleHRlbmQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICB2YXIgc3cgPSB0aGlzLl9zdyxcbiAgICAgICAgICAgIG5lID0gdGhpcy5fbmUsXG4gICAgICAgICAgICBzdzIsIG5lMjtcblxuICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgICAgICBzdzIgPSBvYmo7XG4gICAgICAgICAgICBuZTIgPSBvYmo7XG5cbiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcbiAgICAgICAgICAgIHN3MiA9IG9iai5fc3c7XG4gICAgICAgICAgICBuZTIgPSBvYmouX25lO1xuXG4gICAgICAgICAgICBpZiAoIXN3MiB8fCAhbmUyKSByZXR1cm4gdGhpcztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKExhdExuZy5jb252ZXJ0KG9iaikgfHwgTGF0TG5nQm91bmRzLmNvbnZlcnQob2JqKSkgOiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzdyAmJiAhbmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N3ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcbiAgICAgICAgICAgIHRoaXMuX25lID0gbmV3IExhdExuZyhuZTIubGF0LCBuZTIubG5nKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcbiAgICAgICAgICAgIHN3LmxuZyA9IE1hdGgubWluKHN3Mi5sbmcsIHN3LmxuZyk7XG4gICAgICAgICAgICBuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xuICAgICAgICAgICAgbmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHBvaW50IGVxdWlkaXN0YW50IGZyb20gdGhpcyBib3gncyBjb3JuZXJzXG4gICAgICogQHJldHVybnMge0xhdExuZ30gY2VudGVycG9pbnRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygxMCwgMTApLFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygtMTAsIC0xMCk7XG4gICAgICogYm91bmRzLmdldENlbnRlcigpOyAvLyBlcXVhbHMgbWFwYm94Z2wuTGF0TG5nKDAsIDApXG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmcoKHRoaXMuX3N3LmxhdCArIHRoaXMuX25lLmxhdCkgLyAyLCAodGhpcy5fc3cubG5nICsgdGhpcy5fbmUubG5nKSAvIDIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGh3ZXN0IGNvcm5lclxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9IHNvdXRod2VzdFxuICAgICAqL1xuICAgIGdldFNvdXRoV2VzdDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdzsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBub3J0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbm9ydGhlYXN0XG4gICAgICovXG4gICAgZ2V0Tm9ydGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRod2VzdCBjb3JuZXJcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBub3J0aHdlc3RcbiAgICAgKi9cbiAgICBnZXROb3J0aFdlc3Q6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldE5vcnRoKCksIHRoaXMuZ2V0V2VzdCgpKTsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBzb3V0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gc291dGhlYXN0XG4gICAgICovXG4gICAgZ2V0U291dGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgd2VzdCBlZGdlIGxvbmdpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHdlc3RcbiAgICAgKi9cbiAgICBnZXRXZXN0OiAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdy5sbmc7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGggZWRnZSBsYXRpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHNvdXRoXG4gICAgICovXG4gICAgZ2V0U291dGg6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fc3cubGF0OyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IGVhc3QgZWRnZSBsb25naXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBlYXN0XG4gICAgICovXG4gICAgZ2V0RWFzdDogIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fbmUubG5nOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRoIGVkZ2UgbGF0aXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBub3J0aFxuICAgICAqL1xuICAgIGdldE5vcnRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lLmxhdDsgfVxufTtcblxuLyoqXG4gKiBjb25zdHJ1Y3RzIExhdExuZ0JvdW5kcyBmcm9tIGFuIGFycmF5IGlmIG5lY2Vzc2FyeVxuICogQHBhcmFtIHtMYXRMbmdCb3VuZHN8Kn0gYSBhbnkgaW5wdXRcbiAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN8ZmFsc2V9XG4gKiBAZXhhbXBsZVxuICogLy8gY2FsbHMgTGF0TG5nLmNvbnZlcnQgaW50ZXJuYWxseSB0b1xuICogLy8gc3VwcG9ydCBhcnJheXMgYXMgbGF0bG5nIHZhbHVlc1xuICogTGF0TG5nQm91bmRzLmNvbnZlcnQoW1stMTAsIC0xMF0sIFsxMCwgMTBdXSk7XG4gKi9cbkxhdExuZ0JvdW5kcy5jb252ZXJ0ID0gZnVuY3Rpb24gKGEpIHtcbiAgICBpZiAoIWEgfHwgYSBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykgcmV0dXJuIGE7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpLFxuICAgIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuL2Nvb3JkaW5hdGUnKSxcbiAgICB3cmFwID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJykud3JhcCxcbiAgICBpbnRlcnAgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyksXG4gICAgdmVjNCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLnZlYzQsXG4gICAgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhbnNmb3JtO1xuXG4vKlxuICogQSBzaW5nbGUgdHJhbnNmb3JtLCBnZW5lcmFsbHkgdXNlZCBmb3IgYSBzaW5nbGUgdGlsZSB0byBiZVxuICogc2NhbGVkLCByb3RhdGVkLCBhbmQgem9vbWVkLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtaW5ab29tXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4Wm9vbVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gVHJhbnNmb3JtKG1pblpvb20sIG1heFpvb20pIHtcbiAgICB0aGlzLnRpbGVTaXplID0gNTEyOyAvLyBjb25zdGFudFxuXG4gICAgdGhpcy5fbWluWm9vbSA9IG1pblpvb20gfHwgMDtcbiAgICB0aGlzLl9tYXhab29tID0gbWF4Wm9vbSB8fCAyMjtcblxuICAgIHRoaXMubGF0UmFuZ2UgPSBbLTg1LjA1MTEzLCA4NS4wNTExM107XG5cbiAgICB0aGlzLndpZHRoID0gMDtcbiAgICB0aGlzLmhlaWdodCA9IDA7XG4gICAgdGhpcy56b29tID0gMDtcbiAgICB0aGlzLmNlbnRlciA9IG5ldyBMYXRMbmcoMCwgMCk7XG4gICAgdGhpcy5hbmdsZSA9IDA7XG4gICAgdGhpcy5fYWx0aXR1ZGUgPSAxLjU7XG4gICAgdGhpcy5fcGl0Y2ggPSAwO1xufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlID0ge1xuICAgIGdldCBtaW5ab29tKCkgeyByZXR1cm4gdGhpcy5fbWluWm9vbTsgfSxcbiAgICBzZXQgbWluWm9vbSh6b29tKSB7XG4gICAgICAgIHRoaXMuX21pblpvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnpvb20gPSBNYXRoLm1heCh0aGlzLnpvb20sIHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXQgbWF4Wm9vbSgpIHsgcmV0dXJuIHRoaXMuX21heFpvb207IH0sXG4gICAgc2V0IG1heFpvb20oem9vbSkge1xuICAgICAgICB0aGlzLl9tYXhab29tID0gem9vbTtcbiAgICAgICAgdGhpcy56b29tID0gTWF0aC5taW4odGhpcy56b29tLCB6b29tKTtcbiAgICB9LFxuXG4gICAgZ2V0IHdvcmxkU2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUgKiB0aGlzLnNjYWxlO1xuICAgIH0sXG5cbiAgICBnZXQgY2VudGVyUG9pbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemUuX2RpdigyKTtcbiAgICB9LFxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuICAgIH0sXG5cbiAgICBnZXQgYmVhcmluZygpIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLmFuZ2xlIC8gTWF0aC5QSSAqIDE4MDtcbiAgICB9LFxuICAgIHNldCBiZWFyaW5nKGJlYXJpbmcpIHtcbiAgICAgICAgdGhpcy5hbmdsZSA9IC13cmFwKGJlYXJpbmcsIC0xODAsIDE4MCkgKiBNYXRoLlBJIC8gMTgwO1xuICAgIH0sXG5cbiAgICBnZXQgcGl0Y2goKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9waXRjaCAvIE1hdGguUEkgKiAxODA7XG4gICAgfSxcbiAgICBzZXQgcGl0Y2gocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5fcGl0Y2ggPSBNYXRoLm1pbig2MCwgcGl0Y2gpIC8gMTgwICogTWF0aC5QSTtcbiAgICB9LFxuXG4gICAgZ2V0IGFsdGl0dWRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWx0aXR1ZGU7XG4gICAgfSxcbiAgICBzZXQgYWx0aXR1ZGUoYWx0aXR1ZGUpIHtcbiAgICAgICAgdGhpcy5fYWx0aXR1ZGUgPSBNYXRoLm1heCgwLjc1LCBhbHRpdHVkZSk7XG4gICAgfSxcblxuICAgIGdldCB6b29tKCkgeyByZXR1cm4gdGhpcy5fem9vbTsgfSxcbiAgICBzZXQgem9vbSh6b29tKSB7XG4gICAgICAgIHpvb20gPSBNYXRoLm1pbihNYXRoLm1heCh6b29tLCB0aGlzLm1pblpvb20pLCB0aGlzLm1heFpvb20pO1xuICAgICAgICB0aGlzLl96b29tID0gem9vbTtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHRoaXMuem9vbVNjYWxlKHpvb20pO1xuICAgICAgICB0aGlzLnRpbGVab29tID0gTWF0aC5mbG9vcih6b29tKTtcbiAgICAgICAgdGhpcy56b29tRnJhY3Rpb24gPSB6b29tIC0gdGhpcy50aWxlWm9vbTtcbiAgICAgICAgdGhpcy5fY29uc3RyYWluKCk7XG4gICAgfSxcblxuICAgIHpvb21TY2FsZTogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gTWF0aC5wb3coMiwgem9vbSk7IH0sXG4gICAgc2NhbGVab29tOiBmdW5jdGlvbihzY2FsZSkgeyByZXR1cm4gTWF0aC5sb2coc2NhbGUpIC8gTWF0aC5MTjI7IH0sXG5cbiAgICBwcm9qZWN0OiBmdW5jdGlvbihsYXRsbmcsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IFBvaW50KFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcsIHdvcmxkU2l6ZSksXG4gICAgICAgICAgICB0aGlzLmxhdFkobGF0bG5nLmxhdCwgd29ybGRTaXplKSk7XG4gICAgfSxcblxuICAgIHVucHJvamVjdDogZnVuY3Rpb24ocG9pbnQsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZyhcbiAgICAgICAgICAgIHRoaXMueUxhdChwb2ludC55LCB3b3JsZFNpemUpLFxuICAgICAgICAgICAgdGhpcy54TG5nKHBvaW50LngsIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBnZXQgeCgpIHsgcmV0dXJuIHRoaXMubG5nWCh0aGlzLmNlbnRlci5sbmcpOyB9LFxuICAgIGdldCB5KCkgeyByZXR1cm4gdGhpcy5sYXRZKHRoaXMuY2VudGVyLmxhdCk7IH0sXG5cbiAgICBnZXQgcG9pbnQoKSB7IHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpOyB9LFxuXG4gICAgLyoqXG4gICAgICogbGF0L2xvbiA8LT4gYWJzb2x1dGUgcGl4ZWwgY29vcmRzIGNvbnZlcnNpb25cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbG9uXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG5nWDogZnVuY3Rpb24obG9uLCB3b3JsZFNpemUpIHtcbiAgICAgICAgcmV0dXJuICgxODAgKyBsb24pICogKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLyAzNjA7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBsYXRpdHVkZSB0byBhYnNvbHV0ZSB5IGNvb3JkXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGF0XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbGF0WTogZnVuY3Rpb24obGF0LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkgPSAxODAgLyBNYXRoLlBJICogTWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSSAvIDQgKyBsYXQgKiBNYXRoLlBJIC8gMzYwKSk7XG4gICAgICAgIHJldHVybiAoMTgwIC0geSkgKiAod29ybGRTaXplIHx8IHRoaXMud29ybGRTaXplKSAvIDM2MDtcbiAgICB9LFxuXG4gICAgeExuZzogZnVuY3Rpb24oeCwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiB4ICogMzYwIC8gKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLSAxODA7XG4gICAgfSxcbiAgICB5TGF0OiBmdW5jdGlvbih5LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkyID0gMTgwIC0geSAqIDM2MCAvICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpO1xuICAgICAgICByZXR1cm4gMzYwIC8gTWF0aC5QSSAqIE1hdGguYXRhbihNYXRoLmV4cCh5MiAqIE1hdGguUEkgLyAxODApKSAtIDkwO1xuICAgIH0sXG5cbiAgICBwYW5CeTogZnVuY3Rpb24ob2Zmc2V0KSB7XG4gICAgICAgIHZhciBwb2ludCA9IHRoaXMuY2VudGVyUG9pbnQuX2FkZChvZmZzZXQpO1xuICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMucG9pbnRMb2NhdGlvbihwb2ludCk7XG4gICAgICAgIHRoaXMuX2NvbnN0cmFpbigpO1xuICAgIH0sXG5cbiAgICBzZXRMb2NhdGlvbkF0UG9pbnQ6IGZ1bmN0aW9uKGxhdGxuZywgcG9pbnQpIHtcbiAgICAgICAgdmFyIGMgPSB0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpO1xuICAgICAgICB2YXIgY29vcmRBdFBvaW50ID0gdGhpcy5wb2ludENvb3JkaW5hdGUocG9pbnQpO1xuICAgICAgICB2YXIgY29vcmRDZW50ZXIgPSB0aGlzLnBvaW50Q29vcmRpbmF0ZSh0aGlzLmNlbnRlclBvaW50KTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlID0gY29vcmRBdFBvaW50Ll9zdWIoYyk7XG4gICAgICAgIHRoaXMuY2VudGVyID0gdGhpcy5jb29yZGluYXRlTG9jYXRpb24oY29vcmRDZW50ZXIuX3N1Yih0cmFuc2xhdGUpKTtcblxuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgc2V0Wm9vbUFyb3VuZDogZnVuY3Rpb24oem9vbSwgY2VudGVyKSB7XG4gICAgICAgIHZhciBwID0gdGhpcy5sb2NhdGlvblBvaW50KGNlbnRlcik7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHRoaXMuc2V0TG9jYXRpb25BdFBvaW50KGNlbnRlciwgcCk7XG4gICAgfSxcblxuICAgIHNldEJlYXJpbmdBcm91bmQ6IGZ1bmN0aW9uKGJlYXJpbmcsIGNlbnRlcikge1xuICAgICAgICB2YXIgcCA9IHRoaXMubG9jYXRpb25Qb2ludChjZW50ZXIpO1xuICAgICAgICB0aGlzLmJlYXJpbmcgPSBiZWFyaW5nO1xuICAgICAgICB0aGlzLnNldExvY2F0aW9uQXRQb2ludChjZW50ZXIsIHApO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGxvY2F0aW9uLCByZXR1cm4gdGhlIHNjcmVlbiBwb2ludCB0aGF0IGNvcnJlc3BvbmRzIHRvIGl0XG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZyBsb2NhdGlvblxuICAgICAqIEByZXR1cm5zIHtQb2ludH0gc2NyZWVuIHBvaW50XG4gICAgICovXG4gICAgbG9jYXRpb25Qb2ludDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBwb2ludCBvbiBzY3JlZW4sIHJldHVybiBpdHMgbGF0bG5nXG4gICAgICogQHBhcmFtIHtQb2ludH0gcCBzY3JlZW4gcG9pbnRcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBsYXRsbmcgbG9jYXRpb25cbiAgICAgKi9cbiAgICBwb2ludExvY2F0aW9uOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZShwKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGxhdGxuZywgcmV0dXJuIGFuIHVucm91bmRlZFxuICAgICAqIGNvb3JkaW5hdGUgdGhhdCByZXByZXNlbnRzIGl0IGF0IHRoaXMgdHJhbnNmb3JtJ3Mgem9vbSBsZXZlbCBhbmRcbiAgICAgKiB3b3JsZHNpemUuXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfVxuICAgICAqL1xuICAgIGxvY2F0aW9uQ29vcmRpbmF0ZTogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHZhciBrID0gdGhpcy56b29tU2NhbGUodGhpcy50aWxlWm9vbSkgLyB0aGlzLndvcmxkU2l6ZTtcbiAgICAgICAgcmV0dXJuIG5ldyBDb29yZGluYXRlKFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcpICogayxcbiAgICAgICAgICAgIHRoaXMubGF0WShsYXRsbmcubGF0KSAqIGssXG4gICAgICAgICAgICB0aGlzLnRpbGVab29tKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBDb29yZGluYXRlLCByZXR1cm4gaXRzIGdlb2dyYXBoaWNhbCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbGF0bG5nXG4gICAgICovXG4gICAgY29vcmRpbmF0ZUxvY2F0aW9uOiBmdW5jdGlvbihjb29yZCkge1xuICAgICAgICB2YXIgd29ybGRTaXplID0gdGhpcy56b29tU2NhbGUoY29vcmQuem9vbSk7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKFxuICAgICAgICAgICAgdGhpcy55TGF0KGNvb3JkLnJvdywgd29ybGRTaXplKSxcbiAgICAgICAgICAgIHRoaXMueExuZyhjb29yZC5jb2x1bW4sIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBwb2ludENvb3JkaW5hdGU6IGZ1bmN0aW9uKHAsIHRhcmdldFopIHtcblxuICAgICAgICBpZiAodGFyZ2V0WiA9PT0gdW5kZWZpbmVkKSB0YXJnZXRaID0gMDtcblxuICAgICAgICB2YXIgbWF0cml4ID0gdGhpcy5jb29yZGluYXRlUG9pbnRNYXRyaXgodGhpcy50aWxlWm9vbSk7XG4gICAgICAgIHZhciBpbnZlcnRlZCA9IG1hdDQuaW52ZXJ0KG5ldyBGbG9hdDY0QXJyYXkoMTYpLCBtYXRyaXgpO1xuXG4gICAgICAgIGlmICghaW52ZXJ0ZWQpIHRocm93IFwiZmFpbGVkIHRvIGludmVydCBtYXRyaXhcIjtcblxuICAgICAgICAvLyBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSBjb3JyZWN0IHByb2plY3RlZCB6IHZhbHVlIGZvciB0aGUgcG9pbnQsXG4gICAgICAgIC8vIHVucHJvamVjdCB0d28gcG9pbnRzIHRvIGdldCBhIGxpbmUgYW5kIHRoZW4gZmluZCB0aGUgcG9pbnQgb24gdGhhdFxuICAgICAgICAvLyBsaW5lIHdpdGggej0wXG5cbiAgICAgICAgdmFyIGNvb3JkMCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW3AueCwgcC55LCAwLCAxXSwgaW52ZXJ0ZWQpO1xuICAgICAgICB2YXIgY29vcmQxID0gdmVjNC50cmFuc2Zvcm1NYXQ0KFtdLCBbcC54LCBwLnksIDEsIDFdLCBpbnZlcnRlZCk7XG5cbiAgICAgICAgdmFyIHcwID0gY29vcmQwWzNdO1xuICAgICAgICB2YXIgdzEgPSBjb29yZDFbM107XG4gICAgICAgIHZhciB4MCA9IGNvb3JkMFswXSAvIHcwO1xuICAgICAgICB2YXIgeDEgPSBjb29yZDFbMF0gLyB3MTtcbiAgICAgICAgdmFyIHkwID0gY29vcmQwWzFdIC8gdzA7XG4gICAgICAgIHZhciB5MSA9IGNvb3JkMVsxXSAvIHcxO1xuICAgICAgICB2YXIgejAgPSBjb29yZDBbMl0gLyB3MDtcbiAgICAgICAgdmFyIHoxID0gY29vcmQxWzJdIC8gdzE7XG5cblxuICAgICAgICB2YXIgdCA9IHowID09PSB6MSA/IDAgOiAodGFyZ2V0WiAtIHowKSAvICh6MSAtIHowKTtcblxuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUoXG4gICAgICAgICAgICBpbnRlcnAoeDAsIHgxLCB0KSxcbiAgICAgICAgICAgIGludGVycCh5MCwgeTEsIHQpLFxuICAgICAgICAgICAgdGhpcy50aWxlWm9vbSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgY29vcmRpbmF0ZSwgcmV0dXJuIHRoZSBzY3JlZW4gcG9pbnQgdGhhdCBjb3JyZXNwb25kcyB0byBpdFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7UG9pbnR9IHNjcmVlbiBwb2ludFxuICAgICAqL1xuICAgIGNvb3JkaW5hdGVQb2ludDogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMuY29vcmRpbmF0ZVBvaW50TWF0cml4KGNvb3JkLnpvb20pO1xuICAgICAgICB2YXIgcCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW2Nvb3JkLmNvbHVtbiwgY29vcmQucm93LCAwLCAxXSwgbWF0cml4KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChwWzBdIC8gcFszXSwgcFsxXSAvIHBbM10pO1xuICAgIH0sXG5cbiAgICBjb29yZGluYXRlUG9pbnRNYXRyaXg6IGZ1bmN0aW9uKHopIHtcbiAgICAgICAgdmFyIHByb2ogPSB0aGlzLmdldFByb2pNYXRyaXgoKTtcbiAgICAgICAgdmFyIHNjYWxlID0gdGhpcy53b3JsZFNpemUgLyB0aGlzLnpvb21TY2FsZSh6KTtcbiAgICAgICAgbWF0NC5zY2FsZShwcm9qLCBwcm9qLCBbc2NhbGUsIHNjYWxlLCAxXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkocHJvaiwgdGhpcy5nZXRQaXhlbE1hdHJpeCgpLCBwcm9qKTtcbiAgICAgICAgcmV0dXJuIHByb2o7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIGNvbnZlcnRzIGdsIGNvb3JkaW5hdGVzIC0xLi4xIHRvIHBpeGVscyAwLi53aWR0aFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IG1hdHJpeFxuICAgICAqL1xuICAgIGdldFBpeGVsTWF0cml4OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG0gPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFt0aGlzLndpZHRoIC8gMiwgLXRoaXMuaGVpZ2h0IC8gMiwgMV0pO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbMSwgLTEsIDBdKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgfSxcblxuICAgIF9jb25zdHJhaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VudGVyKSByZXR1cm47XG5cbiAgICAgICAgdmFyIG1pblksIG1heFksIG1pblgsIG1heFgsIHN5LCBzeCwgeDIsIHkyLFxuICAgICAgICAgICAgc2l6ZSA9IHRoaXMuc2l6ZTtcblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgbWluWSA9IHRoaXMubGF0WSh0aGlzLmxhdFJhbmdlWzFdKTtcbiAgICAgICAgICAgIG1heFkgPSB0aGlzLmxhdFkodGhpcy5sYXRSYW5nZVswXSk7XG4gICAgICAgICAgICBzeSA9IG1heFkgLSBtaW5ZIDwgc2l6ZS55ID8gc2l6ZS55IC8gKG1heFkgLSBtaW5ZKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgbWluWCA9IHRoaXMubG5nWCh0aGlzLmxuZ1JhbmdlWzBdKTtcbiAgICAgICAgICAgIG1heFggPSB0aGlzLmxuZ1godGhpcy5sbmdSYW5nZVsxXSk7XG4gICAgICAgICAgICBzeCA9IG1heFggLSBtaW5YIDwgc2l6ZS54ID8gc2l6ZS54IC8gKG1heFggLSBtaW5YKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob3cgbXVjaCB0aGUgbWFwIHNob3VsZCBzY2FsZSB0byBmaXQgdGhlIHNjcmVlbiBpbnRvIGdpdmVuIGxhdGl0dWRlL2xvbmdpdHVkZSByYW5nZXNcbiAgICAgICAgdmFyIHMgPSBNYXRoLm1heChzeCB8fCAwLCBzeSB8fCAwKTtcblxuICAgICAgICBpZiAocykge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnVucHJvamVjdChuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgc3ggPyAobWF4WCArIG1pblgpIC8gMiA6IHRoaXMueCxcbiAgICAgICAgICAgICAgICBzeSA/IChtYXhZICsgbWluWSkgLyAyIDogdGhpcy55KSk7XG4gICAgICAgICAgICB0aGlzLnpvb20gKz0gdGhpcy5zY2FsZVpvb20ocyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHkgPSB0aGlzLnksXG4gICAgICAgICAgICAgICAgaDIgPSBzaXplLnkgLyAyO1xuXG4gICAgICAgICAgICBpZiAoeSAtIGgyIDwgbWluWSkgeTIgPSBtaW5ZICsgaDI7XG4gICAgICAgICAgICBpZiAoeSArIGgyID4gbWF4WSkgeTIgPSBtYXhZIC0gaDI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHggPSB0aGlzLngsXG4gICAgICAgICAgICAgICAgdzIgPSBzaXplLnggLyAyO1xuXG4gICAgICAgICAgICBpZiAoeCAtIHcyIDwgbWluWCkgeDIgPSBtaW5YICsgdzI7XG4gICAgICAgICAgICBpZiAoeCArIHcyID4gbWF4WCkgeDIgPSBtYXhYIC0gdzI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwYW4gdGhlIG1hcCBpZiB0aGUgc2NyZWVuIGdvZXMgb2ZmIHRoZSByYW5nZVxuICAgICAgICBpZiAoeDIgIT09IHVuZGVmaW5lZCB8fCB5MiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMudW5wcm9qZWN0KG5ldyBQb2ludChcbiAgICAgICAgICAgICAgICB4MiAhPT0gdW5kZWZpbmVkID8geDIgOiB0aGlzLngsXG4gICAgICAgICAgICAgICAgeTIgIT09IHVuZGVmaW5lZCA/IHkyIDogdGhpcy55KSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZ2V0UHJvak1hdHJpeDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtID0gbmV3IEZsb2F0NjRBcnJheSgxNik7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgY2VudGVyIHBvaW50IHRvIHRoZSBjZW50ZXIgdG9wIGluIGFsdGl0dWRlIHVuaXRzIHVzaW5nIGxhdyBvZiBzaW5lcy5cbiAgICAgICAgdmFyIGhhbGZGb3YgPSBNYXRoLmF0YW4oMC41IC8gdGhpcy5hbHRpdHVkZSk7XG4gICAgICAgIHZhciB0b3BIYWxmU3VyZmFjZURpc3RhbmNlID0gTWF0aC5zaW4oaGFsZkZvdikgKiB0aGlzLmFsdGl0dWRlIC8gTWF0aC5zaW4oTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCAtIGhhbGZGb3YpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgeiB2YWx1ZSBvZiB0aGUgZmFydGhlc3QgZnJhZ21lbnQgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAgICAgIHZhciBmYXJaID0gTWF0aC5jb3MoTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCkgKiB0b3BIYWxmU3VyZmFjZURpc3RhbmNlICsgdGhpcy5hbHRpdHVkZTtcblxuICAgICAgICBtYXQ0LnBlcnNwZWN0aXZlKG0sIDIgKiBNYXRoLmF0YW4oKHRoaXMuaGVpZ2h0IC8gMikgLyB0aGlzLmFsdGl0dWRlKSwgdGhpcy53aWR0aCAvIHRoaXMuaGVpZ2h0LCAwLjEsIGZhclopO1xuXG4gICAgICAgIG1hdDQudHJhbnNsYXRlKG0sIG0sIFswLCAwLCAtdGhpcy5hbHRpdHVkZV0pO1xuXG4gICAgICAgIC8vIEFmdGVyIHRoZSByb3RhdGVYLCB6IHZhbHVlcyBhcmUgaW4gcGl4ZWwgdW5pdHMuIENvbnZlcnQgdGhlbSB0b1xuICAgICAgICAvLyBhbHRpdHVkZSB1bml0ZXMuIDEgYWx0aXR1ZGUgdW5pdCA9IHRoZSBzY3JlZW4gaGVpZ2h0LlxuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFsxLCAtMSwgMSAvIHRoaXMuaGVpZ2h0XSk7XG5cbiAgICAgICAgbWF0NC5yb3RhdGVYKG0sIG0sIHRoaXMuX3BpdGNoKTtcbiAgICAgICAgbWF0NC5yb3RhdGVaKG0sIG0sIHRoaXMuYW5nbGUpO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbLXRoaXMueCwgLXRoaXMueSwgMF0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBGb250IGRhdGEgRnJvbSBIZXJzaGV5IFNpbXBsZXggRm9udFxuLy8gaHR0cDovL3BhdWxib3Vya2UubmV0L2RhdGFmb3JtYXRzL2hlcnNoZXkvXG52YXIgc2ltcGxleEZvbnQgPSB7XG4gICAgXCIgXCI6IFsxNiwgW11dLFxuICAgIFwiIVwiOiBbMTAsIFs1LCAyMSwgNSwgNywgLTEsIC0xLCA1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCJcXFwiXCI6IFsxNiwgWzQsIDIxLCA0LCAxNCwgLTEsIC0xLCAxMiwgMjEsIDEyLCAxNF1dLFxuICAgIFwiI1wiOiBbMjEsIFsxMSwgMjUsIDQsIC03LCAtMSwgLTEsIDE3LCAyNSwgMTAsIC03LCAtMSwgLTEsIDQsIDEyLCAxOCwgMTIsIC0xLCAtMSwgMywgNiwgMTcsIDZdXSxcbiAgICBcIiRcIjogWzIwLCBbOCwgMjUsIDgsIC00LCAtMSwgLTEsIDEyLCAyNSwgMTIsIC00LCAtMSwgLTEsIDE3LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxLCA1LCAyMCwgMywgMTgsIDMsIDE2LCA0LCAxNCwgNSwgMTMsIDcsIDEyLCAxMywgMTAsIDE1LCA5LCAxNiwgOCwgMTcsIDYsIDE3LCAzLCAxNSwgMSwgMTIsIDAsIDgsIDAsIDUsIDEsIDMsIDNdXSxcbiAgICBcIiVcIjogWzI0LCBbMjEsIDIxLCAzLCAwLCAtMSwgLTEsIDgsIDIxLCAxMCwgMTksIDEwLCAxNywgOSwgMTUsIDcsIDE0LCA1LCAxNCwgMywgMTYsIDMsIDE4LCA0LCAyMCwgNiwgMjEsIDgsIDIxLCAxMCwgMjAsIDEzLCAxOSwgMTYsIDE5LCAxOSwgMjAsIDIxLCAyMSwgLTEsIC0xLCAxNywgNywgMTUsIDYsIDE0LCA0LCAxNCwgMiwgMTYsIDAsIDE4LCAwLCAyMCwgMSwgMjEsIDMsIDIxLCA1LCAxOSwgNywgMTcsIDddXSxcbiAgICBcIiZcIjogWzI2LCBbMjMsIDEyLCAyMywgMTMsIDIyLCAxNCwgMjEsIDE0LCAyMCwgMTMsIDE5LCAxMSwgMTcsIDYsIDE1LCAzLCAxMywgMSwgMTEsIDAsIDcsIDAsIDUsIDEsIDQsIDIsIDMsIDQsIDMsIDYsIDQsIDgsIDUsIDksIDEyLCAxMywgMTMsIDE0LCAxNCwgMTYsIDE0LCAxOCwgMTMsIDIwLCAxMSwgMjEsIDksIDIwLCA4LCAxOCwgOCwgMTYsIDksIDEzLCAxMSwgMTAsIDE2LCAzLCAxOCwgMSwgMjAsIDAsIDIyLCAwLCAyMywgMSwgMjMsIDJdXSxcbiAgICBcIidcIjogWzEwLCBbNSwgMTksIDQsIDIwLCA1LCAyMSwgNiwgMjAsIDYsIDE4LCA1LCAxNiwgNCwgMTVdXSxcbiAgICBcIihcIjogWzE0LCBbMTEsIDI1LCA5LCAyMywgNywgMjAsIDUsIDE2LCA0LCAxMSwgNCwgNywgNSwgMiwgNywgLTIsIDksIC01LCAxMSwgLTddXSxcbiAgICBcIilcIjogWzE0LCBbMywgMjUsIDUsIDIzLCA3LCAyMCwgOSwgMTYsIDEwLCAxMSwgMTAsIDcsIDksIDIsIDcsIC0yLCA1LCAtNSwgMywgLTddXSxcbiAgICBcIipcIjogWzE2LCBbOCwgMjEsIDgsIDksIC0xLCAtMSwgMywgMTgsIDEzLCAxMiwgLTEsIC0xLCAxMywgMTgsIDMsIDEyXV0sXG4gICAgXCIrXCI6IFsyNiwgWzEzLCAxOCwgMTMsIDAsIC0xLCAtMSwgNCwgOSwgMjIsIDldXSxcbiAgICBcIixcIjogWzEwLCBbNiwgMSwgNSwgMCwgNCwgMSwgNSwgMiwgNiwgMSwgNiwgLTEsIDUsIC0zLCA0LCAtNF1dLFxuICAgIFwiLVwiOiBbMjYsIFs0LCA5LCAyMiwgOV1dLFxuICAgIFwiLlwiOiBbMTAsIFs1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCIvXCI6IFsyMiwgWzIwLCAyNSwgMiwgLTddXSxcbiAgICBcIjBcIjogWzIwLCBbOSwgMjEsIDYsIDIwLCA0LCAxNywgMywgMTIsIDMsIDksIDQsIDQsIDYsIDEsIDksIDAsIDExLCAwLCAxNCwgMSwgMTYsIDQsIDE3LCA5LCAxNywgMTIsIDE2LCAxNywgMTQsIDIwLCAxMSwgMjEsIDksIDIxXV0sXG4gICAgXCIxXCI6IFsyMCwgWzYsIDE3LCA4LCAxOCwgMTEsIDIxLCAxMSwgMF1dLFxuICAgIFwiMlwiOiBbMjAsIFs0LCAxNiwgNCwgMTcsIDUsIDE5LCA2LCAyMCwgOCwgMjEsIDEyLCAyMSwgMTQsIDIwLCAxNSwgMTksIDE2LCAxNywgMTYsIDE1LCAxNSwgMTMsIDEzLCAxMCwgMywgMCwgMTcsIDBdXSxcbiAgICBcIjNcIjogWzIwLCBbNSwgMjEsIDE2LCAyMSwgMTAsIDEzLCAxMywgMTMsIDE1LCAxMiwgMTYsIDExLCAxNywgOCwgMTcsIDYsIDE2LCAzLCAxNCwgMSwgMTEsIDAsIDgsIDAsIDUsIDEsIDQsIDIsIDMsIDRdXSxcbiAgICBcIjRcIjogWzIwLCBbMTMsIDIxLCAzLCA3LCAxOCwgNywgLTEsIC0xLCAxMywgMjEsIDEzLCAwXV0sXG4gICAgXCI1XCI6IFsyMCwgWzE1LCAyMSwgNSwgMjEsIDQsIDEyLCA1LCAxMywgOCwgMTQsIDExLCAxNCwgMTQsIDEzLCAxNiwgMTEsIDE3LCA4LCAxNywgNiwgMTYsIDMsIDE0LCAxLCAxMSwgMCwgOCwgMCwgNSwgMSwgNCwgMiwgMywgNF1dLFxuICAgIFwiNlwiOiBbMjAsIFsxNiwgMTgsIDE1LCAyMCwgMTIsIDIxLCAxMCwgMjEsIDcsIDIwLCA1LCAxNywgNCwgMTIsIDQsIDcsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMSwgMCwgMTQsIDEsIDE2LCAzLCAxNywgNiwgMTcsIDcsIDE2LCAxMCwgMTQsIDEyLCAxMSwgMTMsIDEwLCAxMywgNywgMTIsIDUsIDEwLCA0LCA3XV0sXG4gICAgXCI3XCI6IFsyMCwgWzE3LCAyMSwgNywgMCwgLTEsIC0xLCAzLCAyMSwgMTcsIDIxXV0sXG4gICAgXCI4XCI6IFsyMCwgWzgsIDIxLCA1LCAyMCwgNCwgMTgsIDQsIDE2LCA1LCAxNCwgNywgMTMsIDExLCAxMiwgMTQsIDExLCAxNiwgOSwgMTcsIDcsIDE3LCA0LCAxNiwgMiwgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCA0LCAyLCAzLCA0LCAzLCA3LCA0LCA5LCA2LCAxMSwgOSwgMTIsIDEzLCAxMywgMTUsIDE0LCAxNiwgMTYsIDE2LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxXV0sXG4gICAgXCI5XCI6IFsyMCwgWzE2LCAxNCwgMTUsIDExLCAxMywgOSwgMTAsIDgsIDksIDgsIDYsIDksIDQsIDExLCAzLCAxNCwgMywgMTUsIDQsIDE4LCA2LCAyMCwgOSwgMjEsIDEwLCAyMSwgMTMsIDIwLCAxNSwgMTgsIDE2LCAxNCwgMTYsIDksIDE1LCA0LCAxMywgMSwgMTAsIDAsIDgsIDAsIDUsIDEsIDQsIDNdXSxcbiAgICBcIjpcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDUsIDIsIDQsIDEsIDUsIDAsIDYsIDEsIDUsIDJdXSxcbiAgICBcIjtcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDYsIDEsIDUsIDAsIDQsIDEsIDUsIDIsIDYsIDEsIDYsIC0xLCA1LCAtMywgNCwgLTRdXSxcbiAgICBcIjxcIjogWzI0LCBbMjAsIDE4LCA0LCA5LCAyMCwgMF1dLFxuICAgIFwiPVwiOiBbMjYsIFs0LCAxMiwgMjIsIDEyLCAtMSwgLTEsIDQsIDYsIDIyLCA2XV0sXG4gICAgXCI+XCI6IFsyNCwgWzQsIDE4LCAyMCwgOSwgNCwgMF1dLFxuICAgIFwiP1wiOiBbMTgsIFszLCAxNiwgMywgMTcsIDQsIDE5LCA1LCAyMCwgNywgMjEsIDExLCAyMSwgMTMsIDIwLCAxNCwgMTksIDE1LCAxNywgMTUsIDE1LCAxNCwgMTMsIDEzLCAxMiwgOSwgMTAsIDksIDcsIC0xLCAtMSwgOSwgMiwgOCwgMSwgOSwgMCwgMTAsIDEsIDksIDJdXSxcbiAgICBcIkBcIjogWzI3LCBbMTgsIDEzLCAxNywgMTUsIDE1LCAxNiwgMTIsIDE2LCAxMCwgMTUsIDksIDE0LCA4LCAxMSwgOCwgOCwgOSwgNiwgMTEsIDUsIDE0LCA1LCAxNiwgNiwgMTcsIDgsIC0xLCAtMSwgMTIsIDE2LCAxMCwgMTQsIDksIDExLCA5LCA4LCAxMCwgNiwgMTEsIDUsIC0xLCAtMSwgMTgsIDE2LCAxNywgOCwgMTcsIDYsIDE5LCA1LCAyMSwgNSwgMjMsIDcsIDI0LCAxMCwgMjQsIDEyLCAyMywgMTUsIDIyLCAxNywgMjAsIDE5LCAxOCwgMjAsIDE1LCAyMSwgMTIsIDIxLCA5LCAyMCwgNywgMTksIDUsIDE3LCA0LCAxNSwgMywgMTIsIDMsIDksIDQsIDYsIDUsIDQsIDcsIDIsIDksIDEsIDEyLCAwLCAxNSwgMCwgMTgsIDEsIDIwLCAyLCAyMSwgMywgLTEsIC0xLCAxOSwgMTYsIDE4LCA4LCAxOCwgNiwgMTksIDVdXSxcbiAgICBcIkFcIjogWzE4LCBbOSwgMjEsIDEsIDAsIC0xLCAtMSwgOSwgMjEsIDE3LCAwLCAtMSwgLTEsIDQsIDcsIDE0LCA3XV0sXG4gICAgXCJCXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgLTEsIC0xLCA0LCAxMSwgMTMsIDExLCAxNiwgMTAsIDE3LCA5LCAxOCwgNywgMTgsIDQsIDE3LCAyLCAxNiwgMSwgMTMsIDAsIDQsIDBdXSxcbiAgICBcIkNcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1XV0sXG4gICAgXCJEXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMSwgMjEsIDE0LCAyMCwgMTYsIDE4LCAxNywgMTYsIDE4LCAxMywgMTgsIDgsIDE3LCA1LCAxNiwgMywgMTQsIDEsIDExLCAwLCA0LCAwXV0sXG4gICAgXCJFXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxNywgMjEsIC0xLCAtMSwgNCwgMTEsIDEyLCAxMSwgLTEsIC0xLCA0LCAwLCAxNywgMF1dLFxuICAgIFwiRlwiOiBbMTgsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTcsIDIxLCAtMSwgLTEsIDQsIDExLCAxMiwgMTFdXSxcbiAgICBcIkdcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOCwgOCwgLTEsIC0xLCAxMywgOCwgMTgsIDhdXSxcbiAgICBcIkhcIjogWzIyLCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMCwgLTEsIC0xLCA0LCAxMSwgMTgsIDExXV0sXG4gICAgXCJJXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIkpcIjogWzE2LCBbMTIsIDIxLCAxMiwgNSwgMTEsIDIsIDEwLCAxLCA4LCAwLCA2LCAwLCA0LCAxLCAzLCAyLCAyLCA1LCAyLCA3XV0sXG4gICAgXCJLXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDE4LCAyMSwgNCwgNywgLTEsIC0xLCA5LCAxMiwgMTgsIDBdXSxcbiAgICBcIkxcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMCwgMTYsIDBdXSxcbiAgICBcIk1cIjogWzI0LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMjEsIDEyLCAwLCAtMSwgLTEsIDIwLCAyMSwgMTIsIDAsIC0xLCAtMSwgMjAsIDIxLCAyMCwgMF1dLFxuICAgIFwiTlwiOiBbMjIsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTgsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMF1dLFxuICAgIFwiT1wiOiBbMjIsIFs5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOSwgOCwgMTksIDEzLCAxOCwgMTYsIDE3LCAxOCwgMTUsIDIwLCAxMywgMjEsIDksIDIxXV0sXG4gICAgXCJQXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNCwgMTcsIDEyLCAxNiwgMTEsIDEzLCAxMCwgNCwgMTBdXSxcbiAgICBcIlFcIjogWzIyLCBbOSwgMjEsIDcsIDIwLCA1LCAxOCwgNCwgMTYsIDMsIDEzLCAzLCA4LCA0LCA1LCA1LCAzLCA3LCAxLCA5LCAwLCAxMywgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNSwgMTksIDgsIDE5LCAxMywgMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgLTEsIC0xLCAxMiwgNCwgMTgsIC0yXV0sXG4gICAgXCJSXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgNCwgMTEsIC0xLCAtMSwgMTEsIDExLCAxOCwgMF1dLFxuICAgIFwiU1wiOiBbMjAsIFsxNywgMTgsIDE1LCAyMCwgMTIsIDIxLCA4LCAyMSwgNSwgMjAsIDMsIDE4LCAzLCAxNiwgNCwgMTQsIDUsIDEzLCA3LCAxMiwgMTMsIDEwLCAxNSwgOSwgMTYsIDgsIDE3LCA2LCAxNywgMywgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCAzLCAzXV0sXG4gICAgXCJUXCI6IFsxNiwgWzgsIDIxLCA4LCAwLCAtMSwgLTEsIDEsIDIxLCAxNSwgMjFdXSxcbiAgICBcIlVcIjogWzIyLCBbNCwgMjEsIDQsIDYsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMiwgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNiwgMTgsIDIxXV0sXG4gICAgXCJWXCI6IFsxOCwgWzEsIDIxLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMF1dLFxuICAgIFwiV1wiOiBbMjQsIFsyLCAyMSwgNywgMCwgLTEsIC0xLCAxMiwgMjEsIDcsIDAsIC0xLCAtMSwgMTIsIDIxLCAxNywgMCwgLTEsIC0xLCAyMiwgMjEsIDE3LCAwXV0sXG4gICAgXCJYXCI6IFsyMCwgWzMsIDIxLCAxNywgMCwgLTEsIC0xLCAxNywgMjEsIDMsIDBdXSxcbiAgICBcIllcIjogWzE4LCBbMSwgMjEsIDksIDExLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMTFdXSxcbiAgICBcIlpcIjogWzIwLCBbMTcsIDIxLCAzLCAwLCAtMSwgLTEsIDMsIDIxLCAxNywgMjEsIC0xLCAtMSwgMywgMCwgMTcsIDBdXSxcbiAgICBcIltcIjogWzE0LCBbNCwgMjUsIDQsIC03LCAtMSwgLTEsIDUsIDI1LCA1LCAtNywgLTEsIC0xLCA0LCAyNSwgMTEsIDI1LCAtMSwgLTEsIDQsIC03LCAxMSwgLTddXSxcbiAgICBcIlxcXFxcIjogWzE0LCBbMCwgMjEsIDE0LCAtM11dLFxuICAgIFwiXVwiOiBbMTQsIFs5LCAyNSwgOSwgLTcsIC0xLCAtMSwgMTAsIDI1LCAxMCwgLTcsIC0xLCAtMSwgMywgMjUsIDEwLCAyNSwgLTEsIC0xLCAzLCAtNywgMTAsIC03XV0sXG4gICAgXCJeXCI6IFsxNiwgWzYsIDE1LCA4LCAxOCwgMTAsIDE1LCAtMSwgLTEsIDMsIDEyLCA4LCAxNywgMTMsIDEyLCAtMSwgLTEsIDgsIDE3LCA4LCAwXV0sXG4gICAgXCJfXCI6IFsxNiwgWzAsIC0yLCAxNiwgLTJdXSxcbiAgICBcImBcIjogWzEwLCBbNiwgMjEsIDUsIDIwLCA0LCAxOCwgNCwgMTYsIDUsIDE1LCA2LCAxNiwgNSwgMTddXSxcbiAgICBcImFcIjogWzE5LCBbMTUsIDE0LCAxNSwgMCwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJiXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDExLCA2LCAxMywgOCwgMTQsIDExLCAxNCwgMTMsIDEzLCAxNSwgMTEsIDE2LCA4LCAxNiwgNiwgMTUsIDMsIDEzLCAxLCAxMSwgMCwgOCwgMCwgNiwgMSwgNCwgM11dLFxuICAgIFwiY1wiOiBbMTgsIFsxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJkXCI6IFsxOSwgWzE1LCAyMSwgMTUsIDAsIC0xLCAtMSwgMTUsIDExLCAxMywgMTMsIDExLCAxNCwgOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgM11dLFxuICAgIFwiZVwiOiBbMTgsIFszLCA4LCAxNSwgOCwgMTUsIDEwLCAxNCwgMTIsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJmXCI6IFsxMiwgWzEwLCAyMSwgOCwgMjEsIDYsIDIwLCA1LCAxNywgNSwgMCwgLTEsIC0xLCAyLCAxNCwgOSwgMTRdXSxcbiAgICBcImdcIjogWzE5LCBbMTUsIDE0LCAxNSwgLTIsIDE0LCAtNSwgMTMsIC02LCAxMSwgLTcsIDgsIC03LCA2LCAtNiwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJoXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDEwLCA3LCAxMywgOSwgMTQsIDEyLCAxNCwgMTQsIDEzLCAxNSwgMTAsIDE1LCAwXV0sXG4gICAgXCJpXCI6IFs4LCBbMywgMjEsIDQsIDIwLCA1LCAyMSwgNCwgMjIsIDMsIDIxLCAtMSwgLTEsIDQsIDE0LCA0LCAwXV0sXG4gICAgXCJqXCI6IFsxMCwgWzUsIDIxLCA2LCAyMCwgNywgMjEsIDYsIDIyLCA1LCAyMSwgLTEsIC0xLCA2LCAxNCwgNiwgLTMsIDUsIC02LCAzLCAtNywgMSwgLTddXSxcbiAgICBcImtcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTQsIDE0LCA0LCA0LCAtMSwgLTEsIDgsIDgsIDE1LCAwXV0sXG4gICAgXCJsXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIm1cIjogWzMwLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDAsIC0xLCAtMSwgMTUsIDEwLCAxOCwgMTMsIDIwLCAxNCwgMjMsIDE0LCAyNSwgMTMsIDI2LCAxMCwgMjYsIDBdXSxcbiAgICBcIm5cIjogWzE5LCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDBdXSxcbiAgICBcIm9cIjogWzE5LCBbOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgMywgMTYsIDYsIDE2LCA4LCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNF1dLFxuICAgIFwicFwiOiBbMTksIFs0LCAxNCwgNCwgLTcsIC0xLCAtMSwgNCwgMTEsIDYsIDEzLCA4LCAxNCwgMTEsIDE0LCAxMywgMTMsIDE1LCAxMSwgMTYsIDgsIDE2LCA2LCAxNSwgMywgMTMsIDEsIDExLCAwLCA4LCAwLCA2LCAxLCA0LCAzXV0sXG4gICAgXCJxXCI6IFsxOSwgWzE1LCAxNCwgMTUsIC03LCAtMSwgLTEsIDE1LCAxMSwgMTMsIDEzLCAxMSwgMTQsIDgsIDE0LCA2LCAxMywgNCwgMTEsIDMsIDgsIDMsIDYsIDQsIDMsIDYsIDEsIDgsIDAsIDExLCAwLCAxMywgMSwgMTUsIDNdXSxcbiAgICBcInJcIjogWzEzLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgOCwgNSwgMTEsIDcsIDEzLCA5LCAxNCwgMTIsIDE0XV0sXG4gICAgXCJzXCI6IFsxNywgWzE0LCAxMSwgMTMsIDEzLCAxMCwgMTQsIDcsIDE0LCA0LCAxMywgMywgMTEsIDQsIDksIDYsIDgsIDExLCA3LCAxMywgNiwgMTQsIDQsIDE0LCAzLCAxMywgMSwgMTAsIDAsIDcsIDAsIDQsIDEsIDMsIDNdXSxcbiAgICBcInRcIjogWzEyLCBbNSwgMjEsIDUsIDQsIDYsIDEsIDgsIDAsIDEwLCAwLCAtMSwgLTEsIDIsIDE0LCA5LCAxNF1dLFxuICAgIFwidVwiOiBbMTksIFs0LCAxNCwgNCwgNCwgNSwgMSwgNywgMCwgMTAsIDAsIDEyLCAxLCAxNSwgNCwgLTEsIC0xLCAxNSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ2XCI6IFsxNiwgWzIsIDE0LCA4LCAwLCAtMSwgLTEsIDE0LCAxNCwgOCwgMF1dLFxuICAgIFwid1wiOiBbMjIsIFszLCAxNCwgNywgMCwgLTEsIC0xLCAxMSwgMTQsIDcsIDAsIC0xLCAtMSwgMTEsIDE0LCAxNSwgMCwgLTEsIC0xLCAxOSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ4XCI6IFsxNywgWzMsIDE0LCAxNCwgMCwgLTEsIC0xLCAxNCwgMTQsIDMsIDBdXSxcbiAgICBcInlcIjogWzE2LCBbMiwgMTQsIDgsIDAsIC0xLCAtMSwgMTQsIDE0LCA4LCAwLCA2LCAtNCwgNCwgLTYsIDIsIC03LCAxLCAtN11dLFxuICAgIFwielwiOiBbMTcsIFsxNCwgMTQsIDMsIDAsIC0xLCAtMSwgMywgMTQsIDE0LCAxNCwgLTEsIC0xLCAzLCAwLCAxNCwgMF1dLFxuICAgIFwie1wiOiBbMTQsIFs5LCAyNSwgNywgMjQsIDYsIDIzLCA1LCAyMSwgNSwgMTksIDYsIDE3LCA3LCAxNiwgOCwgMTQsIDgsIDEyLCA2LCAxMCwgLTEsIC0xLCA3LCAyNCwgNiwgMjIsIDYsIDIwLCA3LCAxOCwgOCwgMTcsIDksIDE1LCA5LCAxMywgOCwgMTEsIDQsIDksIDgsIDcsIDksIDUsIDksIDMsIDgsIDEsIDcsIDAsIDYsIC0yLCA2LCAtNCwgNywgLTYsIC0xLCAtMSwgNiwgOCwgOCwgNiwgOCwgNCwgNywgMiwgNiwgMSwgNSwgLTEsIDUsIC0zLCA2LCAtNSwgNywgLTYsIDksIC03XV0sXG4gICAgXCJ8XCI6IFs4LCBbNCwgMjUsIDQsIC03XV0sXG4gICAgXCJ9XCI6IFsxNCwgWzUsIDI1LCA3LCAyNCwgOCwgMjMsIDksIDIxLCA5LCAxOSwgOCwgMTcsIDcsIDE2LCA2LCAxNCwgNiwgMTIsIDgsIDEwLCAtMSwgLTEsIDcsIDI0LCA4LCAyMiwgOCwgMjAsIDcsIDE4LCA2LCAxNywgNSwgMTUsIDUsIDEzLCA2LCAxMSwgMTAsIDksIDYsIDcsIDUsIDUsIDUsIDMsIDYsIDEsIDcsIDAsIDgsIC0yLCA4LCAtNCwgNywgLTYsIC0xLCAtMSwgOCwgOCwgNiwgNiwgNiwgNCwgNywgMiwgOCwgMSwgOSwgLTEsIDksIC0zLCA4LCAtNSwgNywgLTYsIDUsIC03XV0sXG4gICAgXCJ+XCI6IFsyNCwgWzMsIDYsIDMsIDgsIDQsIDExLCA2LCAxMiwgOCwgMTIsIDEwLCAxMSwgMTQsIDgsIDE2LCA3LCAxOCwgNywgMjAsIDgsIDIxLCAxMCwgLTEsIC0xLCAzLCA4LCA0LCAxMCwgNiwgMTEsIDgsIDExLCAxMCwgMTAsIDE0LCA3LCAxNiwgNiwgMTgsIDYsIDIwLCA3LCAyMSwgMTAsIDIxLCAxMl1dXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRleHRWZXJ0aWNlcyh0ZXh0LCBsZWZ0LCBiYXNlbGluZSwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDE7XG5cbiAgICB2YXIgc3Ryb2tlcyA9IFtdLFxuICAgICAgICBpLCBsZW4sIGosIGxlbjIsIGdseXBoLCB4LCB5LCBwcmV2O1xuXG4gICAgZm9yIChpID0gMCwgbGVuID0gdGV4dC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBnbHlwaCA9IHNpbXBsZXhGb250W3RleHRbaV1dO1xuICAgICAgICBpZiAoIWdseXBoKSBjb250aW51ZTtcbiAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgZm9yIChqID0gMCwgbGVuMiA9IGdseXBoWzFdLmxlbmd0aDsgaiA8IGxlbjI7IGogKz0gMikge1xuICAgICAgICAgICAgaWYgKGdseXBoWzFdW2pdID09PSAtMSAmJiBnbHlwaFsxXVtqICsgMV0gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeCA9IGxlZnQgKyBnbHlwaFsxXVtqXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIHkgPSBiYXNlbGluZSAtIGdseXBoWzFdW2ogKyAxXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZXMucHVzaChwcmV2LngsIHByZXYueSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXYgPSB7eDogeCwgeTogeX07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGVmdCArPSBnbHlwaFswXSAqIHNjYWxlO1xuICAgIH1cblxuICAgIHJldHVybiBzdHJva2VzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBtYXBib3hnbCBpcyBhIEEgV2ViR0wgSmF2YVNjcmlwdCBpbnRlcmFjdGl2ZSBtYXBzIGxpYnJhcnkgdGhhdCBjYW4gcmVuZGVyXG4gKiBbTWFwYm94IHZlY3RvciB0aWxlc10oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9ibG9nL3ZlY3Rvci10aWxlcy8pLlxuICpcbiAqIEBtb2R1bGUgbWFwYm94Z2xcbiAqIEBzdW1tYXJ5IFdlYkdMIEphdmFTY3JpcHQgbWFwIGxpYnJhcnlcbiAqL1xuXG4vLyBqc2hpbnQgLVcwNzlcbnZhciBtYXBib3hnbCA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbm1hcGJveGdsLk1hcCA9IHJlcXVpcmUoJy4vdWkvbWFwJyk7XG5tYXBib3hnbC5OYXZpZ2F0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL25hdmlnYXRpb24nKTtcbm1hcGJveGdsLkF0dHJpYnV0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL2F0dHJpYnV0aW9uJyk7XG5tYXBib3hnbC5Qb3B1cCA9IHJlcXVpcmUoJy4vdWkvcG9wdXAnKTtcblxubWFwYm94Z2wuR2VvSlNPTlNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL2dlb2pzb25fc291cmNlJyk7XG5tYXBib3hnbC5WaWRlb1NvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL3ZpZGVvX3NvdXJjZScpO1xuXG5tYXBib3hnbC5TdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUvc3R5bGUnKTtcblxubWFwYm94Z2wuTGF0TG5nID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZycpO1xubWFwYm94Z2wuTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbm1hcGJveGdsLlBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubWFwYm94Z2wuRXZlbnRlZCA9IHJlcXVpcmUoJy4vdXRpbC9ldmVudGVkJyk7XG5tYXBib3hnbC51dGlsID0gcmVxdWlyZSgnLi91dGlsL3V0aWwnKTtcblxubWFwYm94Z2wuc3VwcG9ydGVkID0gcmVxdWlyZSgnLi91dGlsL2Jyb3dzZXInKS5zdXBwb3J0ZWQ7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi91dGlsL2FqYXgnKTtcbm1hcGJveGdsLnV0aWwuZ2V0SlNPTiA9IGFqYXguZ2V0SlNPTjtcbm1hcGJveGdsLnV0aWwuZ2V0QXJyYXlCdWZmZXIgPSBhamF4LmdldEFycmF5QnVmZmVyO1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi91dGlsL2NvbmZpZycpO1xubWFwYm94Z2wuY29uZmlnID0gY29uZmlnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWFwYm94Z2wsICdhY2Nlc3NUb2tlbicsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnLkFDQ0VTU19UT0tFTjsgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHRva2VuKSB7IGNvbmZpZy5BQ0NFU1NfVE9LRU4gPSB0b2tlbjsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBtYXQzID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0MztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3QmFja2dyb3VuZDtcblxuZnVuY3Rpb24gZHJhd0JhY2tncm91bmQocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtY29sb3InXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnYmFja2dyb3VuZC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtb3BhY2l0eSddO1xuICAgIHZhciBzaGFkZXI7XG5cbiAgICB2YXIgaW1hZ2VQb3NBID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpIDogbnVsbDtcbiAgICB2YXIgaW1hZ2VQb3NCID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLnRvLCB0cnVlKSA6IG51bGw7XG5cbiAgICBpZiAoaW1hZ2VQb3NBICYmIGltYWdlUG9zQikge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZSwgMCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9hLCBpbWFnZVBvc0EudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYSwgaW1hZ2VQb3NBLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2IsIGltYWdlUG9zQi50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9iLCBpbWFnZVBvc0IuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eSwgb3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgICAgICB2YXIgc2l6ZUEgPSBpbWFnZVBvc0Euc2l6ZTtcbiAgICAgICAgdmFyIHNpemVCID0gaW1hZ2VQb3NCLnNpemU7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0cmFuc2Zvcm0ubG9jYXRpb25Db29yZGluYXRlKHRyYW5zZm9ybS5jZW50ZXIpO1xuICAgICAgICB2YXIgc2NhbGUgPSAxIC8gTWF0aC5wb3coMiwgdHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21peCwgaW1hZ2UudCk7XG5cbiAgICAgICAgdmFyIG1hdHJpeEEgPSBtYXQzLmNyZWF0ZSgpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIDEgLyAoc2l6ZUFbMF0gKiBpbWFnZS5mcm9tU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQVsxXSAqIGltYWdlLmZyb21TY2FsZSlcbiAgICAgICAgXSk7XG4gICAgICAgIG1hdDMudHJhbnNsYXRlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIChjZW50ZXIuY29sdW1uICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQVswXSAqIGltYWdlLmZyb21TY2FsZSksXG4gICAgICAgICAgICAoY2VudGVyLnJvdyAgICAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUFbMV0gKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhBLCBtYXRyaXhBLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICB2YXIgbWF0cml4QiA9IG1hdDMuY3JlYXRlKCk7XG4gICAgICAgIG1hdDMuc2NhbGUobWF0cml4QiwgbWF0cml4QiwgW1xuICAgICAgICAgICAgMSAvIChzaXplQlswXSAqIGltYWdlLnRvU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnRyYW5zbGF0ZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAoY2VudGVyLmNvbHVtbiAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUJbMF0gKiBpbWFnZS50b1NjYWxlKSxcbiAgICAgICAgICAgIChjZW50ZXIucm93ICAgICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhCLCBtYXRyaXhCLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYSwgZmFsc2UsIG1hdHJpeEEpO1xuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYiwgZmFsc2UsIG1hdHJpeEIpO1xuXG4gICAgICAgIHBhaW50ZXIuc3ByaXRlQXRsYXMuYmluZChnbCwgdHJ1ZSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEcmF3IGZpbGxpbmcgcmVjdGFuZ2xlLlxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmZpbGxTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm00ZnYoc2hhZGVyLnVfY29sb3IsIGNvbG9yKTtcbiAgICB9XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIuaXRlbUNvdW50KTtcbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcblxuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3UGxhY2VtZW50RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdQbGFjZW1lbnREZWJ1ZyhwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlKSB7XG5cbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdLmNvbGxpc2lvbkJveDtcbiAgICBpZiAoIWVsZW1lbnRHcm91cHMpIHJldHVybjtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGJ1ZmZlciA9IHRpbGUuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIHNoYWRlciA9IHBhaW50ZXIuY29sbGlzaW9uQm94U2hhZGVyO1xuXG4gICAgZ2wuZW5hYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgIGJ1ZmZlci5iaW5kKGdsLCBzaGFkZXIpO1xuICAgIGdsLmxpbmVXaWR0aCgzKTtcblxuICAgIHZhciBzdHJpZGUgPSAxMjtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZXh0cnVkZSwgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDQpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YSwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgOCk7XG5cbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2NhbGUsIE1hdGgucG93KDIsIHBhaW50ZXIudHJhbnNmb3JtLnpvb20gLSB0aWxlLmNvb3JkLnopKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfem9vbSwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWF4em9vbSwgKHRpbGUuY29vcmQueiArIDEpICogMTApO1xuXG4gICAgdmFyIGJlZ2luID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4U3RhcnRJbmRleDtcbiAgICB2YXIgbGVuID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4TGVuZ3RoO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIGJlZ2luLCBsZW4pO1xuXG4gICAgZ2wuZGlzYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdGV4dFZlcnRpY2VzID0gcmVxdWlyZSgnLi4vbGliL2RlYnVndGV4dCcpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdEZWJ1ZyhwYWludGVyLCB0aWxlKSB7XG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcblxuICAgIC8vIEJsZW5kIHRvIHRoZSBmcm9udCwgbm90IHRoZSBiYWNrLlxuICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZGVidWdTaGFkZXIsIHRpbGUucG9zTWF0cml4KTtcblxuICAgIC8vIGRyYXcgYm91bmRpbmcgcmVjdGFuZ2xlXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuZGVidWdCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z0J1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC51bmlmb3JtNGYocGFpbnRlci5kZWJ1Z1NoYWRlci51X2NvbG9yLCAxLCAwLCAwLCAxKTtcbiAgICBnbC5saW5lV2lkdGgoNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FX1NUUklQLCAwLCBwYWludGVyLmRlYnVnQnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICB2YXIgdmVydGljZXMgPSB0ZXh0VmVydGljZXModGlsZS5jb29yZC50b1N0cmluZygpLCA1MCwgMjAwLCA1KTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmRlYnVnVGV4dEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KHZlcnRpY2VzKSwgZ2wuU1RSRUFNX0RSQVcpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wubGluZVdpZHRoKDggKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDEsIDEsIDEpO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHZlcnRpY2VzLmxlbmd0aCAvIHBhaW50ZXIuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplKTtcbiAgICBnbC5saW5lV2lkdGgoMiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgZ2wudW5pZm9ybTRmKHBhaW50ZXIuZGVidWdTaGFkZXIudV9jb2xvciwgMCwgMCwgMCwgMSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdmVydGljZXMubGVuZ3RoIC8gcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0MyA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDM7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0ZpbGw7XG5cbmZ1bmN0aW9uIGRyYXdGaWxsKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpIHtcbiAgICAvLyBObyBkYXRhXG4gICAgaWYgKCF0aWxlLmJ1ZmZlcnMpIHJldHVybjtcbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdO1xuICAgIGlmICghZWxlbWVudEdyb3VwcykgcmV0dXJuO1xuXG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcbiAgICB2YXIgdHJhbnNsYXRlZFBvc01hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2ZpbGwtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydmaWxsLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgY29sb3IgPSBsYXllci5wYWludFsnZmlsbC1jb2xvciddO1xuXG4gICAgdmFyIHZlcnRleCwgZWxlbWVudHMsIGdyb3VwLCBjb3VudDtcblxuICAgIC8vIERyYXcgdGhlIHN0ZW5jaWwgbWFzay5cblxuICAgIC8vIFdlJ3JlIG9ubHkgZHJhd2luZyB0byB0aGUgZmlyc3Qgc2V2ZW4gYml0cyAoPT0gc3VwcG9ydCBhIG1heGltdW0gb2ZcbiAgICAvLyAxMjcgb3ZlcmxhcHBpbmcgcG9seWdvbnMgaW4gb25lIHBsYWNlIGJlZm9yZSB3ZSBnZXQgcmVuZGVyaW5nIGVycm9ycykuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgzRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIERyYXcgZnJvbnQgZmFjaW5nIHRyaWFuZ2xlcy4gV2hlcmV2ZXIgdGhlIDB4ODAgYml0IGlzIDEsIHdlIGFyZVxuICAgIC8vIGluY3JlYXNpbmcgdGhlIGxvd2VyIDcgYml0cyBieSBvbmUgaWYgdGhlIHRyaWFuZ2xlIGlzIGEgZnJvbnQtZmFjaW5nXG4gICAgLy8gdHJpYW5nbGUuIFRoaXMgbWVhbnMgdGhhdCBhbGwgdmlzaWJsZSBwb2x5Z29ucyBzaG91bGQgYmUgaW4gQ0NXXG4gICAgLy8gb3JpZW50YXRpb24sIHdoaWxlIGFsbCBob2xlcyAoc2VlIGJlbG93KSBhcmUgaW4gQ1cgb3JpZW50YXRpb24uXG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuTk9URVFVQUwsIDB4ODAsIDB4ODApO1xuXG4gICAgLy8gV2hlbiB3ZSBkbyBhIG5vbnplcm8gZmlsbCwgd2UgY291bnQgdGhlIG51bWJlciBvZiB0aW1lcyBhIHBpeGVsIGlzXG4gICAgLy8gY292ZXJlZCBieSBhIGNvdW50ZXJjbG9ja3dpc2UgcG9seWdvbiwgYW5kIHN1YnRyYWN0IHRoZSBudW1iZXIgb2ZcbiAgICAvLyB0aW1lcyBpdCBpcyBcInVuY292ZXJlZFwiIGJ5IGEgY2xvY2t3aXNlIHBvbHlnb24uXG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuRlJPTlQsIGdsLklOQ1JfV1JBUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuQkFDSywgZ2wuREVDUl9XUkFQLCBnbC5LRUVQLCBnbC5LRUVQKTtcblxuICAgIC8vIFdoZW4gZHJhd2luZyBhIHNoYXBlLCB3ZSBmaXJzdCBkcmF3IGFsbCBzaGFwZXMgdG8gdGhlIHN0ZW5jaWwgYnVmZmVyXG4gICAgLy8gYW5kIGluY3JlbWVudGluZyBhbGwgYXJlYXMgd2hlcmUgcG9seWdvbnMgYXJlXG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIERyYXcgdGhlIGFjdHVhbCB0cmlhbmdsZSBmYW4gaW50byB0aGUgc3RlbmNpbCBidWZmZXIuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZmlsbFNoYWRlciwgdHJhbnNsYXRlZFBvc01hdHJpeCk7XG5cbiAgICAvLyBEcmF3IGFsbCBidWZmZXJzXG4gICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIGVsZW1lbnRzLmJpbmQoZ2wpO1xuXG4gICAgdmFyIG9mZnNldCwgZWxlbWVudE9mZnNldDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmZpbGxTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgNCwgb2Zmc2V0ICsgMCk7XG5cbiAgICAgICAgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgc3RlbmNpbCBtYXNrIGluIHRoZSBzdGVuY2lsIGJ1ZmZlciwgd2UgY2FuIHN0YXJ0XG4gICAgLy8gd3JpdGluZyB0byB0aGUgY29sb3IgYnVmZmVyLlxuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcblxuICAgIC8vIEZyb20gbm93IG9uLCB3ZSBkb24ndCB3YW50IHRvIHVwZGF0ZSB0aGUgc3RlbmNpbCBidWZmZXIgYW55bW9yZS5cbiAgICBnbC5zdGVuY2lsT3AoZ2wuS0VFUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwKTtcblxuICAgIHZhciBzdHJva2VDb2xvciA9IGxheWVyLnBhaW50WydmaWxsLW91dGxpbmUtY29sb3InXTtcblxuICAgIC8vIEJlY2F1c2Ugd2UncmUgZHJhd2luZyB0b3AtdG8tYm90dG9tLCBhbmQgd2UgdXBkYXRlIHRoZSBzdGVuY2lsIG1hc2tcbiAgICAvLyBiZWxvdywgd2UgaGF2ZSB0byBkcmF3IHRoZSBvdXRsaW5lIGZpcnN0ICghKVxuICAgIGlmIChsYXllci5wYWludFsnZmlsbC1hbnRpYWxpYXMnXSA9PT0gdHJ1ZSAmJiAhKGxheWVyLnBhaW50WydmaWxsLWltYWdlJ10gJiYgIXN0cm9rZUNvbG9yKSkge1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLCB0cmFuc2xhdGVkUG9zTWF0cml4KTtcbiAgICAgICAgZ2wubGluZVdpZHRoKDIgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuXG4gICAgICAgIGlmIChzdHJva2VDb2xvcikge1xuICAgICAgICAgICAgLy8gSWYgd2UgZGVmaW5lZCBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGZpbGwgb3V0bGluZSwgd2UgYXJlXG4gICAgICAgICAgICAvLyBnb2luZyB0byBpZ25vcmUgdGhlIGJpdHMgaW4gMHgzRiBhbmQganVzdCBjYXJlIGFib3V0IHRoZSBnbG9iYWxcbiAgICAgICAgICAgIC8vIGNsaXBwaW5nIG1hc2suXG4gICAgICAgICAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIG9ubHkgd2FudCB0byBkcmF3IHRoZSBhbnRpYWxpYXNlZCBwYXJ0cyB0aGF0IGFyZVxuICAgICAgICAgICAgLy8gKm91dHNpZGUqIHRoZSBjdXJyZW50IHNoYXBlLiBUaGlzIGlzIGltcG9ydGFudCBpbiBjYXNlIHRoZSBmaWxsXG4gICAgICAgICAgICAvLyBvciBzdHJva2UgY29sb3IgaXMgdHJhbnNsdWNlbnQuIElmIHdlIHdvdWxkbid0IGNsaXAgdG8gb3V0c2lkZVxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2hhcGUsIHNvbWUgcGl4ZWxzIGZyb20gdGhlIG91dGxpbmUgc3Ryb2tlIG92ZXJsYXBwZWRcbiAgICAgICAgICAgIC8vIHRoZSAobm9uLWFudGlhbGlhc2VkKSBmaWxsLlxuICAgICAgICAgICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4QkYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmKHBhaW50ZXIub3V0bGluZVNoYWRlci51X3dvcmxkLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHBhaW50ZXIub3V0bGluZVNoYWRlci51X2NvbG9yLCBzdHJva2VDb2xvciA/IHN0cm9rZUNvbG9yIDogY29sb3IpO1xuXG4gICAgICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICAgICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLm91dGxpbmVFbGVtZW50O1xuICAgICAgICBlbGVtZW50cy5iaW5kKGdsKTtcblxuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDQsIG9mZnNldCArIDApO1xuXG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGggKiAyO1xuICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICBnbC5kcmF3RWxlbWVudHMoZ2wuTElORVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnZmlsbC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2ZpbGwtb3BhY2l0eSddIHx8IDE7XG4gICAgdmFyIHNoYWRlcjtcblxuICAgIGlmIChpbWFnZSkge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICB2YXIgaW1hZ2VQb3NBID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS5mcm9tLCB0cnVlKTtcbiAgICAgICAgdmFyIGltYWdlUG9zQiA9IHBhaW50ZXIuc3ByaXRlQXRsYXMuZ2V0UG9zaXRpb24oaW1hZ2UudG8sIHRydWUpO1xuICAgICAgICBpZiAoIWltYWdlUG9zQSB8fCAhaW1hZ2VQb3NCKSByZXR1cm47XG5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5wYXR0ZXJuU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtMWkoc2hhZGVyLnVfaW1hZ2UsIDApO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYSwgaW1hZ2VQb3NBLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2EsIGltYWdlUG9zQS5icik7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9iLCBpbWFnZVBvc0IudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYiwgaW1hZ2VQb3NCLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIG9wYWNpdHkpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBpbWFnZS50KTtcblxuICAgICAgICB2YXIgZmFjdG9yID0gKHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUpIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gLSB0aWxlLmNvb3JkLnopO1xuXG4gICAgICAgIHZhciBtYXRyaXhBID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQS5zaXplWzBdICogZmFjdG9yICogaW1hZ2UuZnJvbVNjYWxlKSxcbiAgICAgICAgICAgIDEgLyAoaW1hZ2VQb3NBLnNpemVbMV0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHZhciBtYXRyaXhCID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzBdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSksXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzFdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSlcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2EsIGZhbHNlLCBtYXRyaXhBKTtcbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2IsIGZhbHNlLCBtYXRyaXhCKTtcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRHJhdyBmaWxsaW5nIHJlY3RhbmdsZS5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5maWxsU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgLy8gT25seSBkcmF3IHJlZ2lvbnMgdGhhdCB3ZSBtYXJrZWRcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHgwLCAweDNGKTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4ODApO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDIgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQyO1xuXG4vKipcbiAqIERyYXcgYSBsaW5lLiBVbmRlciB0aGUgaG9vZCB0aGlzIHdpbGwgcmVhZCBlbGVtZW50cyBmcm9tXG4gKiBhIHRpbGUsIGRhc2ggdGV4dHVyZXMgZnJvbSBhIGxpbmVBdGxhcywgYW5kIHN0eWxlIHByb3BlcnRpZXMgZnJvbSBhIGxheWVyLlxuICogQHBhcmFtIHtPYmplY3R9IHBhaW50ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXllclxuICogQHBhcmFtIHtPYmplY3R9IHBvc01hdHJpeFxuICogQHBhcmFtIHtUaWxlfSB0aWxlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBkcmF3cyB3aXRoIHRoZSBwYWludGVyXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhd0xpbmUocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuXG4gICAgLy8gZG9uJ3QgZHJhdyB6ZXJvLXdpZHRoIGxpbmVzXG4gICAgaWYgKGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ10gPD0gMCkgcmV0dXJuO1xuXG4gICAgLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXG4gICAgLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXG4gICAgdmFyIGFudGlhbGlhc2luZyA9IDEgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICB2YXIgYmx1ciA9IGxheWVyLnBhaW50WydsaW5lLWJsdXInXSArIGFudGlhbGlhc2luZztcbiAgICB2YXIgZWRnZVdpZHRoID0gbGF5ZXIucGFpbnRbJ2xpbmUtd2lkdGgnXSAvIDI7XG4gICAgdmFyIGluc2V0ID0gLTE7XG4gICAgdmFyIG9mZnNldCA9IDA7XG4gICAgdmFyIHNoaWZ0ID0gMDtcblxuICAgIGlmIChsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSA+IDApIHtcbiAgICAgICAgaW5zZXQgPSBsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSAvIDIgKyBhbnRpYWxpYXNpbmcgKiAwLjU7XG4gICAgICAgIGVkZ2VXaWR0aCA9IGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ107XG5cbiAgICAgICAgLy8gc2hpZnQgb3V0ZXIgbGluZXMgaGFsZiBhIHBpeGVsIHRvd2FyZHMgdGhlIG1pZGRsZSB0byBlbGltaW5hdGUgdGhlIGNyYWNrXG4gICAgICAgIG9mZnNldCA9IGluc2V0IC0gYW50aWFsaWFzaW5nIC8gMjtcbiAgICB9XG5cbiAgICB2YXIgb3V0c2V0ID0gb2Zmc2V0ICsgZWRnZVdpZHRoICsgYW50aWFsaWFzaW5nIC8gMiArIHNoaWZ0O1xuXG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2xpbmUtY29sb3InXTtcbiAgICB2YXIgcmF0aW8gPSBwYWludGVyLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHZ0eE1hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2xpbmUtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydsaW5lLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgdHIgPSBwYWludGVyLnRyYW5zZm9ybTtcblxuXG4gICAgdmFyIGFudGlhbGlhc2luZ01hdHJpeCA9IG1hdDIuY3JlYXRlKCk7XG4gICAgbWF0Mi5zY2FsZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgWzEsIE1hdGguY29zKHRyLl9waXRjaCldKTtcbiAgICBtYXQyLnJvdGF0ZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgcGFpbnRlci50cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIGxvbmdlciB0aGUgcmVhbCB3b3JsZCBkaXN0YW5jZSBpcyBhdCB0aGUgdG9wIG9mIHRoZSBzY3JlZW5cbiAgICAvLyB0aGFuIGF0IHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbi5cbiAgICB2YXIgdG9wZWRnZWxlbmd0aCA9IE1hdGguc3FydCh0ci5oZWlnaHQgKiB0ci5oZWlnaHQgLyA0ICAqICgxICsgdHIuYWx0aXR1ZGUgKiB0ci5hbHRpdHVkZSkpO1xuICAgIHZhciB4ID0gdHIuaGVpZ2h0IC8gMiAqIE1hdGgudGFuKHRyLl9waXRjaCk7XG4gICAgdmFyIGV4dHJhID0gKHRvcGVkZ2VsZW5ndGggKyB4KSAvIHRvcGVkZ2VsZW5ndGggLSAxO1xuXG4gICAgLy8gaG93IG11Y2ggdGhlIHRpbGUgaXMgb3ZlcnNjYWxlZCBieVxuICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUudGlsZVNpemUgLyBwYWludGVyLnRyYW5zZm9ybS50aWxlU2l6ZTtcblxuICAgIHZhciBzaGFkZXI7XG5cblxuICAgIHZhciBkYXNoYXJyYXkgPSBsYXllci5wYWludFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnbGluZS1pbWFnZSddO1xuXG4gICAgaWYgKGRhc2hhcnJheSkge1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXNkZnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgY29sb3IpO1xuXG4gICAgICAgIHZhciBwb3NBID0gcGFpbnRlci5saW5lQXRsYXMuZ2V0RGFzaChkYXNoYXJyYXkuZnJvbSwgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgdmFyIHBvc0IgPSBwYWludGVyLmxpbmVBdGxhcy5nZXREYXNoKGRhc2hhcnJheS50bywgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgcGFpbnRlci5saW5lQXRsYXMuYmluZChnbCk7XG5cbiAgICAgICAgdmFyIHBhdHRlcm5yYXRpbyA9IE1hdGgucG93KDIsIE1hdGguZmxvb3IoTWF0aC5sb2cocGFpbnRlci50cmFuc2Zvcm0uc2NhbGUpIC8gTWF0aC5MTjIpIC0gdGlsZS5jb29yZC56KSAvIDggKiBvdmVyc2NhbGluZztcbiAgICAgICAgdmFyIHNjYWxlQSA9IFtwYXR0ZXJucmF0aW8gLyBwb3NBLndpZHRoIC8gZGFzaGFycmF5LmZyb21TY2FsZSwgLXBvc0EuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUEgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkuZnJvbVNjYWxlICogcG9zQS53aWR0aCAqIDI1NiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbykgLyAyO1xuICAgICAgICB2YXIgc2NhbGVCID0gW3BhdHRlcm5yYXRpbyAvIHBvc0Iud2lkdGggLyBkYXNoYXJyYXkudG9TY2FsZSwgLXBvc0IuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUIgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkudG9TY2FsZSAqIHBvc0Iud2lkdGggKiAyNTYgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pIC8gMjtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5zY2FsZV9hLCBzY2FsZUEpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfdGV4X3lfYSwgcG9zQS55KTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuc2NhbGVfYiwgc2NhbGVCKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3RleF95X2IsIHBvc0IueSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlLCAwKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NkZmdhbW1hLCBNYXRoLm1heChnYW1tYUEsIGdhbW1hQikpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBkYXNoYXJyYXkudCk7XG5cbiAgICB9IGVsc2UgaWYgKGltYWdlKSB7XG4gICAgICAgIHZhciBpbWFnZVBvc0EgPSBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpO1xuICAgICAgICB2YXIgaW1hZ2VQb3NCID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS50bywgdHJ1ZSk7XG4gICAgICAgIGlmICghaW1hZ2VQb3NBIHx8ICFpbWFnZVBvc0IpIHJldHVybjtcbiAgICAgICAgdmFyIGZhY3RvciA9IHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUgLyBNYXRoLnBvdygyLCBwYWludGVyLnRyYW5zZm9ybS50aWxlWm9vbSAtIHRpbGUuY29vcmQueikgKiBvdmVyc2NhbGluZztcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9hLCBbaW1hZ2VQb3NBLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUsIGltYWdlUG9zQi5zaXplWzFdIF0pO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9iLCBbaW1hZ2VQb3NCLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS50b1NjYWxlLCBpbWFnZVBvc0Iuc2l6ZVsxXSBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2EsIGltYWdlUG9zQS50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9hLCBpbWFnZVBvc0EuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYiwgaW1hZ2VQb3NCLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2IsIGltYWdlUG9zQi5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlLCBpbWFnZS50KTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIGxheWVyLnBhaW50WydsaW5lLW9wYWNpdHknXSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmxpbmVTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2V4dHJhLCBleHRyYSk7XG4gICAgICAgIGdsLnVuaWZvcm1NYXRyaXgyZnYoc2hhZGVyLnVfYW50aWFsaWFzaW5nbWF0cml4LCBmYWxzZSwgYW50aWFsaWFzaW5nTWF0cml4KTtcblxuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgdmFyIHZlcnRleCA9IHRpbGUuYnVmZmVycy5saW5lVmVydGV4O1xuICAgIHZlcnRleC5iaW5kKGdsKTtcbiAgICB2YXIgZWxlbWVudCA9IHRpbGUuYnVmZmVycy5saW5lRWxlbWVudDtcbiAgICBlbGVtZW50LmJpbmQoZ2wpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50R3JvdXBzLmdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHZ0eE9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIHZ0eE9mZnNldCArIDApO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGEsIDQsIGdsLkJZVEUsIGZhbHNlLCA4LCB2dHhPZmZzZXQgKyA0KTtcblxuICAgICAgICB2YXIgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgdmFyIGVsZW1lbnRPZmZzZXQgPSBncm91cC5lbGVtZW50U3RhcnRJbmRleCAqIGVsZW1lbnQuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdSYXN0ZXI7XG5cbmZ1bmN0aW9uIGRyYXdSYXN0ZXIocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICB2YXIgc2hhZGVyID0gcGFpbnRlci5yYXN0ZXJTaGFkZXI7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4KTtcblxuICAgIC8vIGNvbG9yIHBhcmFtZXRlcnNcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnJpZ2h0bmVzc19sb3csIGxheWVyLnBhaW50WydyYXN0ZXItYnJpZ2h0bmVzcy1taW4nXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2JyaWdodG5lc3NfaGlnaCwgbGF5ZXIucGFpbnRbJ3Jhc3Rlci1icmlnaHRuZXNzLW1heCddKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2F0dXJhdGlvbl9mYWN0b3IsIHNhdHVyYXRpb25GYWN0b3IobGF5ZXIucGFpbnRbJ3Jhc3Rlci1zYXR1cmF0aW9uJ10pKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfY29udHJhc3RfZmFjdG9yLCBjb250cmFzdEZhY3RvcihsYXllci5wYWludFsncmFzdGVyLWNvbnRyYXN0J10pKTtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlci51X3NwaW5fd2VpZ2h0cywgc3BpbldlaWdodHMobGF5ZXIucGFpbnRbJ3Jhc3Rlci1odWUtcm90YXRlJ10pKTtcblxuICAgIHZhciBwYXJlbnRUaWxlID0gdGlsZS5zb3VyY2UgJiYgdGlsZS5zb3VyY2UuX3B5cmFtaWQuZmluZExvYWRlZFBhcmVudCh0aWxlLmNvb3JkLCAwLCB7fSksXG4gICAgICAgIG9wYWNpdGllcyA9IGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgcGFpbnRlci50cmFuc2Zvcm0pO1xuXG4gICAgdmFyIHBhcmVudFNjYWxlQnksIHBhcmVudFRMO1xuXG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcblxuICAgIGlmIChwYXJlbnRUaWxlKSB7XG4gICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTEpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBwYXJlbnRUaWxlLnRleHR1cmUpO1xuXG4gICAgICAgIHBhcmVudFNjYWxlQnkgPSBNYXRoLnBvdygyLCBwYXJlbnRUaWxlLmNvb3JkLnogLSB0aWxlLmNvb3JkLnopO1xuICAgICAgICBwYXJlbnRUTCA9IFt0aWxlLmNvb3JkLnggKiBwYXJlbnRTY2FsZUJ5ICUgMSwgdGlsZS5jb29yZC55ICogcGFyZW50U2NhbGVCeSAlIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wYWNpdGllc1sxXSA9IDA7XG4gICAgfVxuXG4gICAgLy8gY3Jvc3MtZmFkZSBwYXJhbWV0ZXJzXG4gICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV90bF9wYXJlbnQsIHBhcmVudFRMIHx8IFswLCAwXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NjYWxlX3BhcmVudCwgcGFyZW50U2NhbGVCeSB8fCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyX3NjYWxlLCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eTAsIG9wYWNpdGllc1swXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHkxLCBvcGFjaXRpZXNbMV0pO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTAsIDApO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTEsIDEpO1xuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRpbGUuYm91bmRzQnVmZmVyIHx8IHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlcik7XG5cbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgICAgICAgICAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfdGV4dHVyZV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgOCwgNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbn1cblxuZnVuY3Rpb24gc3BpbldlaWdodHMoYW5nbGUpIHtcbiAgICBhbmdsZSAqPSBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBzID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIHZhciBjID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHJldHVybiBbXG4gICAgICAgICgyICogYyArIDEpIC8gMyxcbiAgICAgICAgKC1NYXRoLnNxcnQoMykgKiBzIC0gYyArIDEpIC8gMyxcbiAgICAgICAgKE1hdGguc3FydCgzKSAqIHMgLSBjICsgMSkgLyAzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY29udHJhc3RGYWN0b3IoY29udHJhc3QpIHtcbiAgICByZXR1cm4gY29udHJhc3QgPiAwID9cbiAgICAgICAgMSAvICgxIC0gY29udHJhc3QpIDpcbiAgICAgICAgMSArIGNvbnRyYXN0O1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0aW9uRmFjdG9yKHNhdHVyYXRpb24pIHtcbiAgICByZXR1cm4gc2F0dXJhdGlvbiA+IDAgP1xuICAgICAgICAxIC0gMSAvICgxLjAwMSAtIHNhdHVyYXRpb24pIDpcbiAgICAgICAgLXNhdHVyYXRpb247XG59XG5cbmZ1bmN0aW9uIGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgdHJhbnNmb3JtKSB7XG4gICAgaWYgKCF0aWxlLnNvdXJjZSkgcmV0dXJuIFsxLCAwXTtcblxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIHZhciBmYWRlRHVyYXRpb24gPSBsYXllci5wYWludFsncmFzdGVyLWZhZGUtZHVyYXRpb24nXTtcbiAgICB2YXIgc2luY2VUaWxlID0gKG5vdyAtIHRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbjtcbiAgICB2YXIgc2luY2VQYXJlbnQgPSBwYXJlbnRUaWxlID8gKG5vdyAtIHBhcmVudFRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbiA6IC0xO1xuXG4gICAgdmFyIGlkZWFsWiA9IHRpbGUuc291cmNlLl9weXJhbWlkLmNvdmVyaW5nWm9vbUxldmVsKHRyYW5zZm9ybSk7XG4gICAgdmFyIHBhcmVudEZ1cnRoZXIgPSBwYXJlbnRUaWxlID8gTWF0aC5hYnMocGFyZW50VGlsZS5jb29yZC56IC0gaWRlYWxaKSA+IE1hdGguYWJzKHRpbGUuY29vcmQueiAtIGlkZWFsWikgOiBmYWxzZTtcblxuICAgIHZhciBvcGFjaXR5ID0gW107XG4gICAgaWYgKCFwYXJlbnRUaWxlIHx8IHBhcmVudEZ1cnRoZXIpIHtcbiAgICAgICAgLy8gaWYgbm8gcGFyZW50IG9yIHBhcmVudCBpcyBvbGRlclxuICAgICAgICBvcGFjaXR5WzBdID0gdXRpbC5jbGFtcChzaW5jZVRpbGUsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIHlvdW5nZXIsIHpvb21pbmcgb3V0XG4gICAgICAgIG9wYWNpdHlbMF0gPSB1dGlsLmNsYW1wKDEgLSBzaW5jZVBhcmVudCwgMCwgMSk7XG4gICAgICAgIG9wYWNpdHlbMV0gPSAxIC0gb3BhY2l0eVswXTtcbiAgICB9XG5cbiAgICB2YXIgb3AgPSBsYXllci5wYWludFsncmFzdGVyLW9wYWNpdHknXTtcbiAgICBvcGFjaXR5WzBdICo9IG9wO1xuICAgIG9wYWNpdHlbMV0gKj0gb3A7XG5cbiAgICByZXR1cm4gb3BhY2l0eTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBtYXQ0ID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0NDtcblxudmFyIGRyYXdDb2xsaXNpb25EZWJ1ZyA9IHJlcXVpcmUoJy4vZHJhd19jb2xsaXNpb25fZGVidWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3U3ltYm9scztcblxuZnVuY3Rpb24gZHJhd1N5bWJvbHMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZHJhd0Fjcm9zc0VkZ2VzID0gIShsYXllci5sYXlvdXRbJ3RleHQtYWxsb3ctb3ZlcmxhcCddIHx8IGxheWVyLmxheW91dFsnaWNvbi1hbGxvdy1vdmVybGFwJ10gfHxcbiAgICAgICAgbGF5ZXIubGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXllci5sYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKTtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoZHJhd0Fjcm9zc0VkZ2VzKSB7XG4gICAgICAgIC8vIERpc2FibGUgdGhlIHN0ZW5jaWwgdGVzdCBzbyB0aGF0IGxhYmVscyBhcmVuJ3QgY2xpcHBlZCB0byB0aWxlIGJvdW5kYXJpZXMuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIExheWVycyB3aXRoIGZlYXR1cmVzIHRoYXQgbWF5IGJlIGRyYXduIG92ZXJsYXBwaW5nIGFyZW4ndCBjbGlwcGVkLiBUaGVzZVxuICAgICAgICAvLyBsYXllcnMgYXJlIHNvcnRlZCBpbiB0aGUgeSBkaXJlY3Rpb24sIGFuZCB0byBkcmF3IHRoZSBjb3JyZWN0IG9yZGVyaW5nIG5lYXJcbiAgICAgICAgLy8gdGlsZSBlZGdlcyB0aGUgaWNvbnMgYXJlIGluY2x1ZGVkIGluIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgd2hlbiBkcmF3aW5nLlxuICAgICAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRHcm91cHMudGV4dC5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2wocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSwgZWxlbWVudEdyb3Vwcy50ZXh0LCAndGV4dCcsIHRydWUpO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudEdyb3Vwcy5pY29uLmdyb3Vwcy5sZW5ndGgpIHtcbiAgICAgICAgZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLmljb24sICdpY29uJywgZWxlbWVudEdyb3Vwcy5zZGZJY29ucyk7XG4gICAgfVxuXG4gICAgZHJhd0NvbGxpc2lvbkRlYnVnKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKGRyYXdBY3Jvc3NFZGdlcykge1xuICAgICAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0U2l6ZXMgPSB7XG4gICAgaWNvbjogMSxcbiAgICB0ZXh0OiAyNFxufTtcblxuZnVuY3Rpb24gZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLCBwcmVmaXgsIHNkZikge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBwb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHRpbGUsIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlLWFuY2hvciddKTtcblxuICAgIHZhciB0ciA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgIHZhciBhbGlnbmVkV2l0aE1hcCA9IGxheWVyLmxheW91dFtwcmVmaXggKyAnLXJvdGF0aW9uLWFsaWdubWVudCddID09PSAnbWFwJztcbiAgICB2YXIgc2tld2VkID0gYWxpZ25lZFdpdGhNYXA7XG4gICAgdmFyIGV4TWF0cml4LCBzLCBnYW1tYVNjYWxlO1xuXG4gICAgaWYgKHNrZXdlZCkge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIHMgPSB0aWxlLnRpbGVFeHRlbnQgLyB0aWxlLnRpbGVTaXplIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAtIHRpbGUuY29vcmQueik7XG4gICAgICAgIGdhbW1hU2NhbGUgPSAxIC8gTWF0aC5jb3ModHIuX3BpdGNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY2xvbmUodGlsZS5leE1hdHJpeCk7XG4gICAgICAgIHMgPSBwYWludGVyLnRyYW5zZm9ybS5hbHRpdHVkZTtcbiAgICAgICAgZ2FtbWFTY2FsZSA9IDE7XG4gICAgfVxuICAgIG1hdDQuc2NhbGUoZXhNYXRyaXgsIGV4TWF0cml4LCBbcywgcywgMV0pO1xuXG4gICAgLy8gSWYgbGF5ZXIucGFpbnQuc2l6ZSA+IGxheWVyLmxheW91dFtwcmVmaXggKyAnLW1heC1zaXplJ10gdGhlbiBsYWJlbHMgbWF5IGNvbGxpZGVcbiAgICB2YXIgZm9udFNpemUgPSBsYXllci5wYWludFtwcmVmaXggKyAnLXNpemUnXTtcbiAgICB2YXIgZm9udFNjYWxlID0gZm9udFNpemUgLyBkZWZhdWx0U2l6ZXNbcHJlZml4XTtcbiAgICBtYXQ0LnNjYWxlKGV4TWF0cml4LCBleE1hdHJpeCwgWyBmb250U2NhbGUsIGZvbnRTY2FsZSwgMSBdKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBob3cgbXVjaCBsb25nZXIgdGhlIHJlYWwgd29ybGQgZGlzdGFuY2UgaXMgYXQgdGhlIHRvcCBvZiB0aGUgc2NyZWVuXG4gICAgLy8gdGhhbiBhdCB0aGUgbWlkZGxlIG9mIHRoZSBzY3JlZW4uXG4gICAgdmFyIHRvcGVkZ2VsZW5ndGggPSBNYXRoLnNxcnQodHIuaGVpZ2h0ICogdHIuaGVpZ2h0IC8gNCAgKiAoMSArIHRyLmFsdGl0dWRlICogdHIuYWx0aXR1ZGUpKTtcbiAgICB2YXIgeCA9IHRyLmhlaWdodCAvIDIgKiBNYXRoLnRhbih0ci5fcGl0Y2gpO1xuICAgIHZhciBleHRyYSA9ICh0b3BlZGdlbGVuZ3RoICsgeCkgLyB0b3BlZGdlbGVuZ3RoIC0gMTtcblxuICAgIHZhciB0ZXh0ID0gcHJlZml4ID09PSAndGV4dCc7XG4gICAgdmFyIHNoYWRlciwgdmVydGV4LCBlbGVtZW50cywgdGV4c2l6ZTtcblxuICAgIGlmICghdGV4dCAmJiAhcGFpbnRlci5zdHlsZS5zcHJpdGUubG9hZGVkKCkpXG4gICAgICAgIHJldHVybjtcblxuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgaWYgKHNkZikge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnNkZlNoYWRlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmljb25TaGFkZXI7XG4gICAgfVxuXG4gICAgaWYgKHRleHQpIHtcbiAgICAgICAgcGFpbnRlci5nbHlwaEF0bGFzLnVwZGF0ZVRleHR1cmUoZ2wpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmdseXBoRWxlbWVudDtcbiAgICAgICAgdGV4c2l6ZSA9IFtwYWludGVyLmdseXBoQXRsYXMud2lkdGggLyA0LCBwYWludGVyLmdseXBoQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcGFpbnRlci5zcHJpdGVBdGxhcy5iaW5kKGdsLCBhbGlnbmVkV2l0aE1hcCB8fCBwYWludGVyLm9wdGlvbnMucm90YXRpbmcgfHxcbiAgICAgICAgICAgIHBhaW50ZXIub3B0aW9ucy56b29taW5nIHx8IGZvbnRTY2FsZSAhPT0gMSB8fCBzZGYgfHwgcGFpbnRlci50cmFuc2Zvcm0ucGl0Y2gpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgZWxlbWVudHMgPSB0aWxlLmJ1ZmZlcnMuaWNvbkVsZW1lbnQ7XG4gICAgICAgIHRleHNpemUgPSBbcGFpbnRlci5zcHJpdGVBdGxhcy53aWR0aCAvIDQsIHBhaW50ZXIuc3ByaXRlQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfVxuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3RleHR1cmUsIDApO1xuICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfdGV4c2l6ZSwgdGV4c2l6ZSk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3NrZXdlZCwgc2tld2VkKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZXh0cmEsIGV4dHJhKTtcblxuICAgIC8vIGFkanVzdCBtaW4vbWF4IHpvb21zIGZvciB2YXJpYWJsZSBmb250IHNpZXNcbiAgICB2YXIgem9vbUFkanVzdCA9IE1hdGgubG9nKGZvbnRTaXplIC8gbGF5ZXIubGF5b3V0W3ByZWZpeCArICctbWF4LXNpemUnXSkgLyBNYXRoLkxOMiB8fCAwO1xuXG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3pvb20sIChwYWludGVyLnRyYW5zZm9ybS56b29tIC0gem9vbUFkanVzdCkgKiAxMCk7IC8vIGN1cnJlbnQgem9vbSBsZXZlbFxuXG4gICAgdmFyIGYgPSBwYWludGVyLmZyYW1lSGlzdG9yeS5nZXRGYWRlUHJvcGVydGllcygzMDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlZGlzdCwgZi5mYWRlZGlzdCAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWluZmFkZXpvb20sIE1hdGguZmxvb3IoZi5taW5mYWRlem9vbSAqIDEwKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21heGZhZGV6b29tLCBNYXRoLmZsb29yKGYubWF4ZmFkZXpvb20gKiAxMCkpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlem9vbSwgKHBhaW50ZXIudHJhbnNmb3JtLnpvb20gKyBmLmJ1bXApICogMTApO1xuXG4gICAgdmFyIGdyb3VwLCBvZmZzZXQsIGNvdW50LCBlbGVtZW50T2Zmc2V0O1xuXG4gICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICBpZiAoc2RmKSB7XG4gICAgICAgIHZhciBzZGZQeCA9IDg7XG4gICAgICAgIHZhciBibHVyT2Zmc2V0ID0gMS4xOTtcbiAgICAgICAgdmFyIGhhbG9PZmZzZXQgPSA2O1xuICAgICAgICB2YXIgZ2FtbWEgPSAwLjEwNSAqIGRlZmF1bHRTaXplc1twcmVmaXhdIC8gZm9udFNpemUgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCBnYW1tYSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBsYXllci5wYWludFtwcmVmaXggKyAnLWNvbG9yJ10pO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyLCAoMjU2IC0gNjQpIC8gMjU2KTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2ldO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pIHtcbiAgICAgICAgICAgIC8vIERyYXcgaGFsbyB1bmRlcm5lYXRoIHRoZSB0ZXh0LlxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWJsdXInXSAqIGJsdXJPZmZzZXQgLyBmb250U2NhbGUgLyBzZGZQeCArIGdhbW1hKSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgbGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKGhhbG9PZmZzZXQgLSBsYXllci5wYWludFtwcmVmaXggKyAnLWhhbG8td2lkdGgnXSAvIGZvbnRTY2FsZSkgLyBzZGZQeCk7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2pdO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgdmVydGV4LmJpbmQoZ2wsIHNoYWRlciwgb2Zmc2V0KTtcblxuICAgICAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBsYXllci5wYWludFsnaWNvbi1vcGFjaXR5J10pO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd1ZlcnRpY2VzO1xuXG5mdW5jdGlvbiBkcmF3VmVydGljZXMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoIXRpbGUgfHwgIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICBpZiAobGF5ZXIudHlwZSA9PT0gJ2ZpbGwnKSB7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXgsIGVsZW1lbnRHcm91cHMuZ3JvdXBzLCBwb3NNYXRyaXgsIDQpO1xuICAgIH0gZWxzZSBpZiAobGF5ZXIudHlwZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleCwgZWxlbWVudEdyb3Vwcy5pY29uLmdyb3VwcywgcG9zTWF0cml4LCAxNik7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmdseXBoVmVydGV4LCBlbGVtZW50R3JvdXBzLnRleHQuZ3JvdXBzLCBwb3NNYXRyaXgsIDE2KTtcbiAgICB9IGVsc2UgaWYgKGxheWVyLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgICB2YXIgbmV3UG9zTWF0cml4ID0gbWF0NC5jbG9uZShwb3NNYXRyaXgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG5ld1Bvc01hdHJpeCwgbmV3UG9zTWF0cml4LCBbMC41LCAwLjUsIDFdKTtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMubGluZVZlcnRleCwgZWxlbWVudEdyb3Vwcy5ncm91cHMsIG5ld1Bvc01hdHJpeCwgOCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1BvaW50cyh2ZXJ0ZXgsIGdyb3VwcywgbWF0cml4LCBzdHJpZGUpIHtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZG90U2hhZGVyLCBtYXRyaXgpO1xuXG4gICAgICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X3NpemUsIDQgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICBnbC51bmlmb3JtMWYocGFpbnRlci5kb3RTaGFkZXIudV9ibHVyLCAwLjI1KTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihwYWludGVyLmRvdFNoYWRlci51X2NvbG9yLCBbMC4xLCAwLCAwLCAwLjFdKTtcblxuICAgICAgICB2ZXJ0ZXguYmluZChnbCwgcGFpbnRlci5kb3RTaGFkZXIsIDApO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldO1xuICAgICAgICAgICAgdmFyIGJlZ2luID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgICAgIHZhciBjb3VudCA9IGdyb3VwLnZlcnRleExlbmd0aDtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kb3RTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCAwKTtcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCBiZWdpbiwgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gRnJhbWVIaXN0b3J5O1xuXG5mdW5jdGlvbiBGcmFtZUhpc3RvcnkoKSB7XG4gICAgdGhpcy5mcmFtZUhpc3RvcnkgPSBbXTtcbn1cblxuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5nZXRGYWRlUHJvcGVydGllcyA9IGZ1bmN0aW9uKGR1cmF0aW9uKSB7XG4gICAgaWYgKGR1cmF0aW9uID09PSB1bmRlZmluZWQpIGR1cmF0aW9uID0gMzAwO1xuICAgIHZhciBjdXJyZW50VGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBSZW1vdmUgZnJhbWVzIHVudGlsIG9ubHkgb25lIGlzIG91dHNpZGUgdGhlIGR1cmF0aW9uLCBvciB1bnRpbCB0aGVyZSBhcmUgb25seSB0aHJlZVxuICAgIHdoaWxlICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPiAzICYmIHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5LnNoaWZ0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5WzBdLnogPSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56O1xuICAgIH1cblxuICAgIHZhciBmcmFtZUxlbiA9IHRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aDtcbiAgICBpZiAoZnJhbWVMZW4gPCAzKSBjb25zb2xlLndhcm4oJ3RoZXJlIHNob3VsZCBuZXZlciBiZSBsZXNzIHRoYW4gdGhyZWUgZnJhbWVzIGluIHRoZSBoaXN0b3J5Jyk7XG5cbiAgICAvLyBGaW5kIHRoZSByYW5nZSBvZiB6b29tIGxldmVscyB3ZSB3YW50IHRvIGZhZGUgYmV0d2VlblxuICAgIHZhciBzdGFydGluZ1ogPSB0aGlzLmZyYW1lSGlzdG9yeVswXS56LFxuICAgICAgICBsYXN0RnJhbWUgPSB0aGlzLmZyYW1lSGlzdG9yeVtmcmFtZUxlbiAtIDFdLFxuICAgICAgICBlbmRpbmdaID0gbGFzdEZyYW1lLnosXG4gICAgICAgIGxvd1ogPSBNYXRoLm1pbihzdGFydGluZ1osIGVuZGluZ1opLFxuICAgICAgICBoaWdoWiA9IE1hdGgubWF4KHN0YXJ0aW5nWiwgZW5kaW5nWik7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHNwZWVkIG9mIHpvb21pbmcsIGFuZCBob3cgZmFyIGl0IHdvdWxkIHpvb20gaW4gdGVybXMgb2Ygem9vbSBsZXZlbHMgaW4gb25lIGR1cmF0aW9uXG4gICAgdmFyIHpvb21EaWZmID0gbGFzdEZyYW1lLnogLSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56LFxuICAgICAgICB0aW1lRGlmZiA9IGxhc3RGcmFtZS50aW1lIC0gdGhpcy5mcmFtZUhpc3RvcnlbMV0udGltZTtcbiAgICB2YXIgZmFkZWRpc3QgPSB6b29tRGlmZiAvICh0aW1lRGlmZiAvIGR1cmF0aW9uKTtcblxuICAgIGlmIChpc05hTihmYWRlZGlzdCkpIGNvbnNvbGUud2FybignZmFkZWRpc3Qgc2hvdWxkIG5ldmVyIGJlIE5hTicpO1xuXG4gICAgLy8gQXQgZW5kIG9mIGEgem9vbSB3aGVuIHRoZSB6b29tIHN0b3BzIGNoYW5naW5nIGNvbnRpbnVlIHByZXRlbmRpbmcgdG8gem9vbSBhdCB0aGF0IHNwZWVkXG4gICAgLy8gYnVtcCBpcyBob3cgbXVjaCBmYXJ0aGVyIGl0IHdvdWxkIGhhdmUgYmVlbiBpZiBpdCBoYWQgY29udGludWVkIHpvb21pbmcgYXQgdGhlIHNhbWUgcmF0ZVxuICAgIHZhciBidW1wID0gKGN1cnJlbnRUaW1lIC0gbGFzdEZyYW1lLnRpbWUpIC8gZHVyYXRpb24gKiBmYWRlZGlzdDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhZGVkaXN0OiBmYWRlZGlzdCxcbiAgICAgICAgbWluZmFkZXpvb206IGxvd1osXG4gICAgICAgIG1heGZhZGV6b29tOiBoaWdoWixcbiAgICAgICAgYnVtcDogYnVtcFxuICAgIH07XG59O1xuXG4vLyBSZWNvcmQgZnJhbWUgaGlzdG9yeSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYWxjdWxhdGUgZmFkaW5nIHBhcmFtc1xuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5yZWNvcmQgPSBmdW5jdGlvbih6b29tKSB7XG4gICAgdmFyIGN1cnJlbnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuICAgIC8vIGZpcnN0IGZyYW1lIGV2ZXJcbiAgICBpZiAoIXRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aCkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHt0aW1lOiAwLCB6OiB6b29tIH0sIHt0aW1lOiAwLCB6OiB6b29tIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPT09IDIgfHwgdGhpcy5mcmFtZUhpc3RvcnlbdGhpcy5mcmFtZUhpc3RvcnkubGVuZ3RoIC0gMV0ueiAhPT0gem9vbSkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHtcbiAgICAgICAgICAgIHRpbWU6IGN1cnJlbnRUaW1lLFxuICAgICAgICAgICAgejogem9vbVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxuZXhwb3J0cy5leHRlbmQgPSBmdW5jdGlvbihjb250ZXh0KSB7XG4gICAgdmFyIG9yaWdMaW5lV2lkdGggPSBjb250ZXh0LmxpbmVXaWR0aCxcbiAgICAgICAgbGluZVdpZHRoUmFuZ2UgPSBjb250ZXh0LmdldFBhcmFtZXRlcihjb250ZXh0LkFMSUFTRURfTElORV9XSURUSF9SQU5HRSk7XG5cbiAgICBjb250ZXh0LmxpbmVXaWR0aCA9IGZ1bmN0aW9uKHdpZHRoKSB7XG4gICAgICAgIG9yaWdMaW5lV2lkdGguY2FsbChjb250ZXh0LCB1dGlsLmNsYW1wKHdpZHRoLCBsaW5lV2lkdGhSYW5nZVswXSwgbGluZVdpZHRoUmFuZ2VbMV0pKTtcbiAgICB9O1xuXG4gICAgY29udGV4dC5nZXRTaGFkZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlKSB7XG4gICAgICAgIHZhciBraW5kID0gdHlwZSA9PT0gdGhpcy5GUkFHTUVOVF9TSEFERVIgPyAnZnJhZ21lbnQnIDogJ3ZlcnRleCc7XG4gICAgICAgIGlmICghc2hhZGVyc1tuYW1lXSB8fCAhc2hhZGVyc1tuYW1lXVtraW5kXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgc2hhZGVyIFwiICsgbmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hhZGVyID0gdGhpcy5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgIHRoaXMuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyc1tuYW1lXVtraW5kXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICBpZiAoIXRoaXMuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgdGhpcy5DT01QSUxFX1NUQVRVUykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNoYWRlcjtcbiAgICB9O1xuXG4gICAgY29udGV4dC5pbml0aWFsaXplU2hhZGVyID0gZnVuY3Rpb24obmFtZSwgYXR0cmlidXRlcywgdW5pZm9ybXMpIHtcbiAgICAgICAgdmFyIHNoYWRlciA9IHtcbiAgICAgICAgICAgIHByb2dyYW06IHRoaXMuY3JlYXRlUHJvZ3JhbSgpLFxuICAgICAgICAgICAgZnJhZ21lbnQ6IHRoaXMuZ2V0U2hhZGVyKG5hbWUsIHRoaXMuRlJBR01FTlRfU0hBREVSKSxcbiAgICAgICAgICAgIHZlcnRleDogdGhpcy5nZXRTaGFkZXIobmFtZSwgdGhpcy5WRVJURVhfU0hBREVSKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYXR0YWNoU2hhZGVyKHNoYWRlci5wcm9ncmFtLCBzaGFkZXIudmVydGV4KTtcbiAgICAgICAgdGhpcy5hdHRhY2hTaGFkZXIoc2hhZGVyLnByb2dyYW0sIHNoYWRlci5mcmFnbWVudCk7XG4gICAgICAgIHRoaXMubGlua1Byb2dyYW0oc2hhZGVyLnByb2dyYW0pO1xuXG4gICAgICAgIGlmICghdGhpcy5nZXRQcm9ncmFtUGFyYW1ldGVyKHNoYWRlci5wcm9ncmFtLCB0aGlzLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLmdldFByb2dyYW1JbmZvTG9nKHNoYWRlci5wcm9ncmFtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJbYXR0cmlidXRlc1tpXV0gPSB0aGlzLmdldEF0dHJpYkxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCBhdHRyaWJ1dGVzW2ldKTtcbiAgICAgICAgICAgICAgICBzaGFkZXIuYXR0cmlidXRlcy5wdXNoKHNoYWRlclthdHRyaWJ1dGVzW2ldXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHVuaWZvcm1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgc2hhZGVyW3VuaWZvcm1zW2tdXSA9IHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCB1bmlmb3Jtc1trXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH07XG5cbiAgICAvLyBTd2l0Y2hlcyB0byBhIGRpZmZlcmVudCBzaGFkZXIgcHJvZ3JhbS5cbiAgICBjb250ZXh0LnN3aXRjaFNoYWRlciA9IGZ1bmN0aW9uKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCkge1xuICAgICAgICBpZiAoIXBvc01hdHJpeCkge1xuICAgICAgICAgICAgY29uc29sZS50cmFjZSgncG9zTWF0cml4IGRvZXMgbm90IGhhdmUgcmVxdWlyZWQgYXJndW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTaGFkZXIgIT09IHNoYWRlcikge1xuICAgICAgICAgICAgdGhpcy51c2VQcm9ncmFtKHNoYWRlci5wcm9ncmFtKTtcblxuICAgICAgICAgICAgLy8gRGlzYWJsZSBhbGwgYXR0cmlidXRlcyBmcm9tIHRoZSBleGlzdGluZyBzaGFkZXIgdGhhdCBhcmVuJ3QgdXNlZCBpblxuICAgICAgICAgICAgLy8gdGhlIG5ldyBzaGFkZXIuIE5vdGU6IGF0dHJpYnV0ZSBpbmRpY2VzIGFyZSAqbm90KiBwcm9ncmFtIHNwZWNpZmljIVxuICAgICAgICAgICAgdmFyIGVuYWJsZWQgPSB0aGlzLmN1cnJlbnRTaGFkZXIgPyB0aGlzLmN1cnJlbnRTaGFkZXIuYXR0cmlidXRlcyA6IFtdO1xuICAgICAgICAgICAgdmFyIHJlcXVpcmVkID0gc2hhZGVyLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW5hYmxlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlZC5pbmRleE9mKGVuYWJsZWRbaV0pIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShlbmFibGVkW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVuYWJsZSBhbGwgYXR0cmlidXRlcyBmb3IgdGhlIG5ldyBzaGFkZXIuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlcXVpcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVuYWJsZWQuaW5kZXhPZihyZXF1aXJlZFtqXSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkocmVxdWlyZWRbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U2hhZGVyID0gc2hhZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtYXRyaWNlcyBpZiBuZWNlc3NhcnkuIE5vdGU6IFRoaXMgcmVsaWVzIG9uIG9iamVjdCBpZGVudGl0eSFcbiAgICAgICAgLy8gVGhpcyBtZWFucyBjaGFuZ2luZyB0aGUgbWF0cml4IHZhbHVlcyB3aXRob3V0IHRoZSBhY3R1YWwgbWF0cml4IG9iamVjdFxuICAgICAgICAvLyB3aWxsIEZBSUwgdG8gdXBkYXRlIHRoZSBtYXRyaXggcHJvcGVybHkuXG4gICAgICAgIGlmIChzaGFkZXIucG9zTWF0cml4ICE9PSBwb3NNYXRyaXgpIHtcbiAgICAgICAgICAgIHRoaXMudW5pZm9ybU1hdHJpeDRmdihzaGFkZXIudV9tYXRyaXgsIGZhbHNlLCBwb3NNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLnBvc01hdHJpeCA9IHBvc01hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhNYXRyaXggJiYgc2hhZGVyLmV4TWF0cml4ICE9PSBleE1hdHJpeCAmJiBzaGFkZXIudV9leG1hdHJpeCkge1xuICAgICAgICAgICAgdGhpcy51bmlmb3JtTWF0cml4NGZ2KHNoYWRlci51X2V4bWF0cml4LCBmYWxzZSwgZXhNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLmV4TWF0cml4ID0gZXhNYXRyaXg7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVBdGxhcztcblxuLyoqXG4gKiBNdWNoIGxpa2UgYSBHbHlwaEF0bGFzLCBhIExpbmVBdGxhcyBsZXRzIHVzIHJldXNlIHJlbmRlcmVkIGRhc2hlZCBsaW5lc1xuICogYnkgd3JpdGluZyBtYW55IG9mIHRoZW0gdG8gYSB0ZXh0dXJlIGFuZCB0aGVuIGZldGNoaW5nIHRoZWlyIHBvc2l0aW9uc1xuICogdXNpbmcgLmdldERhc2guXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBMaW5lQXRsYXMod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLm5leHRSb3cgPSAwO1xuXG4gICAgdGhpcy5ieXRlcyA9IDQ7XG4gICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy53aWR0aCAqIHRoaXMuaGVpZ2h0ICogdGhpcy5ieXRlcyk7XG5cbiAgICB0aGlzLnBvc2l0aW9ucyA9IHt9O1xufVxuXG5MaW5lQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuLyoqXG4gKiBHZXQgb3IgY3JlYXRlIGEgZGFzaCBsaW5lIHBhdHRlcm4uXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBkYXNoYXJyYXlcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gcm91bmQgd2hldGhlciB0byBhZGQgY2lyY2xlIGNhcHMgaW4gYmV0d2VlbiBkYXNoIHNlZ21lbnRzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwb3NpdGlvbiBvZiBkYXNoIHRleHR1cmUgaW4geyB5LCBoZWlnaHQsIHdpZHRoIH1cbiAqIEBwcml2YXRlXG4gKi9cbkxpbmVBdGxhcy5wcm90b3R5cGUuZ2V0RGFzaCA9IGZ1bmN0aW9uKGRhc2hhcnJheSwgcm91bmQpIHtcbiAgICB2YXIga2V5ID0gZGFzaGFycmF5LmpvaW4oXCIsXCIpICsgcm91bmQ7XG5cbiAgICBpZiAoIXRoaXMucG9zaXRpb25zW2tleV0pIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbnNba2V5XSA9IHRoaXMuYWRkRGFzaChkYXNoYXJyYXksIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucG9zaXRpb25zW2tleV07XG59O1xuXG5MaW5lQXRsYXMucHJvdG90eXBlLmFkZERhc2ggPSBmdW5jdGlvbihkYXNoYXJyYXksIHJvdW5kKSB7XG5cbiAgICB2YXIgbiA9IHJvdW5kID8gNyA6IDA7XG4gICAgdmFyIGhlaWdodCA9IDIgKiBuICsgMTtcbiAgICB2YXIgb2Zmc2V0ID0gMTI4O1xuXG4gICAgaWYgKHRoaXMubmV4dFJvdyArIGhlaWdodCA+IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTGluZUF0bGFzIG91dCBvZiBzcGFjZScpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhc2hhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZW5ndGggKz0gZGFzaGFycmF5W2ldO1xuICAgIH1cblxuICAgIHZhciBzdHJldGNoID0gdGhpcy53aWR0aCAvIGxlbmd0aDtcbiAgICB2YXIgaGFsZldpZHRoID0gc3RyZXRjaCAvIDI7XG5cbiAgICAvLyBJZiBkYXNoYXJyYXkgaGFzIGFuIG9kZCBsZW5ndGgsIGJvdGggdGhlIGZpcnN0IGFuZCBsYXN0IHBhcnRzXG4gICAgLy8gYXJlIGRhc2hlcyBhbmQgc2hvdWxkIGJlIGpvaW5lZCBzZWFtbGVzc2x5LlxuICAgIHZhciBvZGRMZW5ndGggPSBkYXNoYXJyYXkubGVuZ3RoICUgMiA9PT0gMTtcblxuICAgIGZvciAodmFyIHkgPSAtbjsgeSA8PSBuOyB5KyspIHtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMubmV4dFJvdyArIG4gKyB5O1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLndpZHRoICogcm93O1xuXG4gICAgICAgIHZhciBsZWZ0ID0gb2RkTGVuZ3RoID8gLWRhc2hhcnJheVtkYXNoYXJyYXkubGVuZ3RoIC0gMV0gOiAwO1xuICAgICAgICB2YXIgcmlnaHQgPSBkYXNoYXJyYXlbMF07XG4gICAgICAgIHZhciBwYXJ0SW5kZXggPSAxO1xuXG4gICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgdGhpcy53aWR0aDsgeCsrKSB7XG5cbiAgICAgICAgICAgIHdoaWxlIChyaWdodCA8IHggLyBzdHJldGNoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQgKyBkYXNoYXJyYXlbcGFydEluZGV4XTtcblxuICAgICAgICAgICAgICAgIGlmIChvZGRMZW5ndGggJiYgcGFydEluZGV4ID09PSBkYXNoYXJyYXkubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICByaWdodCArPSBkYXNoYXJyYXlbMF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcGFydEluZGV4Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBkaXN0TGVmdCA9IE1hdGguYWJzKHggLSBsZWZ0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdFJpZ2h0ID0gTWF0aC5hYnMoeCAtIHJpZ2h0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdCA9IE1hdGgubWluKGRpc3RMZWZ0LCBkaXN0UmlnaHQpO1xuICAgICAgICAgICAgdmFyIGluc2lkZSA9IChwYXJ0SW5kZXggJSAyKSA9PT0gMTtcbiAgICAgICAgICAgIHZhciBzaWduZWREaXN0YW5jZTtcblxuICAgICAgICAgICAgaWYgKHJvdW5kKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGNpcmNsZSBjYXBzXG4gICAgICAgICAgICAgICAgdmFyIGRpc3RNaWRkbGUgPSBuID8geSAvIG4gKiAoaGFsZldpZHRoICsgMSkgOiAwO1xuICAgICAgICAgICAgICAgIGlmIChpbnNpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RFZGdlID0gaGFsZldpZHRoIC0gTWF0aC5hYnMoZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgICAgIHNpZ25lZERpc3RhbmNlID0gTWF0aC5zcXJ0KGRpc3QgKiBkaXN0ICsgZGlzdEVkZ2UgKiBkaXN0RWRnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2lnbmVkRGlzdGFuY2UgPSBoYWxmV2lkdGggLSBNYXRoLnNxcnQoZGlzdCAqIGRpc3QgKyBkaXN0TWlkZGxlICogZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduZWREaXN0YW5jZSA9IChpbnNpZGUgPyAxIDogLTEpICogZGlzdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5kYXRhWzMgKyAoaW5kZXggKyB4KSAqIDRdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBzaWduZWREaXN0YW5jZSArIG9mZnNldCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHtcbiAgICAgICAgeTogKHRoaXMubmV4dFJvdyArIG4gKyAwLjUpIC8gdGhpcy5oZWlnaHQsXG4gICAgICAgIGhlaWdodDogMiAqIG4gLyB0aGlzLmhlaWdodCxcbiAgICAgICAgd2lkdGg6IGxlbmd0aFxuICAgIH07XG5cbiAgICB0aGlzLm5leHRSb3cgKz0gaGVpZ2h0O1xuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHBvcztcbn07XG5cbkxpbmVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHRoaXMuZGF0YSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuXG4gICAgICAgIGlmICh0aGlzLmRpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLmRhdGEpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuTGluZUF0bGFzLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIGNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgY2FudmFzLnN0eWxlLnRvcCA9IDA7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAwO1xuICAgIGNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kID0gJyNmZjAnO1xuXG4gICAgY2FudmFzLndpZHRoID0gdGhpcy53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdmFyIGRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5zZGYpIHtcbiAgICAgICAgICAgIHZhciBrID0gaSAqIDQ7XG4gICAgICAgICAgICBkYXRhLmRhdGFba10gPSBkYXRhLmRhdGFbayArIDFdID0gZGF0YS5kYXRhW2sgKyAyXSA9IDA7XG4gICAgICAgICAgICBkYXRhLmRhdGFbayArIDNdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0YS5kYXRhW2ldID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5wdXRJbWFnZURhdGEoZGF0YSwgMCwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2x1dGlsID0gcmVxdWlyZSgnLi9nbF91dGlsJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDQgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQ0O1xudmFyIEZyYW1lSGlzdG9yeSA9IHJlcXVpcmUoJy4vZnJhbWVfaGlzdG9yeScpO1xuXG4vKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBwYWludGVyIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0NhbnZhc30gZ2wgYW4gZXhwZXJpbWVudGFsLXdlYmdsIGRyYXdpbmcgY29udGV4dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IFBhaW50ZXI7XG5mdW5jdGlvbiBQYWludGVyKGdsLCB0cmFuc2Zvcm0pIHtcbiAgICB0aGlzLmdsID0gZ2x1dGlsLmV4dGVuZChnbCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5cbiAgICB0aGlzLnJldXNhYmxlVGV4dHVyZXMgPSB7fTtcbiAgICB0aGlzLnByZUZib3MgPSB7fTtcblxuICAgIHRoaXMuZnJhbWVIaXN0b3J5ID0gbmV3IEZyYW1lSGlzdG9yeSgpO1xuXG4gICAgdGhpcy5zZXR1cCgpO1xufVxuXG4vKlxuICogVXBkYXRlIHRoZSBHTCB2aWV3cG9ydCwgcHJvamVjdGlvbiBtYXRyaXgsIGFuZCB0cmFuc2Zvcm1zIHRvIGNvbXBlbnNhdGVcbiAqIGZvciBhIG5ldyB3aWR0aCBhbmQgaGVpZ2h0IHZhbHVlLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcblxuICAgIHRoaXMud2lkdGggPSB3aWR0aCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICBnbC52aWV3cG9ydCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cbn07XG5cblxuUGFpbnRlci5wcm90b3R5cGUuc2V0dXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgZ2wudmVyYm9zZSA9IHRydWU7XG5cbiAgICAvLyBXZSBhcmUgYmxlbmRpbmcgdGhlIG5ldyBwaXhlbHMgKmJlaGluZCogdGhlIGV4aXN0aW5nIHBpeGVscy4gVGhhdCB3YXkgd2UgY2FuXG4gICAgLy8gZHJhdyBmcm9udC10by1iYWNrIGFuZCB1c2UgdGhlbiBzdGVuY2lsIGJ1ZmZlciB0byBjdWxsIG9wYXF1ZSBwaXhlbHMgZWFybHkuXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKTtcbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FX01JTlVTX0RTVF9BTFBIQSwgZ2wuT05FKTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFkZXJzXG4gICAgdGhpcy5kZWJ1Z1NoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2RlYnVnJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfcG9pbnRzaXplJywgJ3VfY29sb3InXSk7XG5cbiAgICB0aGlzLmdhdXNzaWFuU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZ2F1c3NpYW4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9pbWFnZScsICd1X29mZnNldCddKTtcblxuICAgIHRoaXMucmFzdGVyU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcigncmFzdGVyJyxcbiAgICAgICAgWydhX3BvcycsICdhX3RleHR1cmVfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9icmlnaHRuZXNzX2xvdycsICd1X2JyaWdodG5lc3NfaGlnaCcsICd1X3NhdHVyYXRpb25fZmFjdG9yJywgJ3Vfc3Bpbl93ZWlnaHRzJywgJ3VfY29udHJhc3RfZmFjdG9yJywgJ3Vfb3BhY2l0eTAnLCAndV9vcGFjaXR5MScsICd1X2ltYWdlMCcsICd1X2ltYWdlMScsICd1X3RsX3BhcmVudCcsICd1X3NjYWxlX3BhcmVudCcsICd1X2J1ZmZlcl9zY2FsZSddKTtcblxuICAgIHRoaXMubGluZVNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2xpbmUnLFxuICAgICAgICBbJ2FfcG9zJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfbGluZXdpZHRoJywgJ3VfY29sb3InLCAndV9yYXRpbycsICd1X2JsdXInLCAndV9leHRyYScsICd1X2FudGlhbGlhc2luZ21hdHJpeCddKTtcblxuICAgIHRoaXMubGluZXBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X3JhdGlvJywgJ3VfcGF0dGVybl9zaXplX2EnLCAndV9wYXR0ZXJuX3NpemVfYicsICd1X3BhdHRlcm5fdGxfYScsICd1X3BhdHRlcm5fYnJfYScsICd1X3BhdHRlcm5fdGxfYicsICd1X3BhdHRlcm5fYnJfYicsICd1X2JsdXInLCAndV9mYWRlJywgJ3Vfb3BhY2l0eSddKTtcblxuICAgIHRoaXMubGluZXNkZnBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lc2RmcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X2NvbG9yJywgJ3VfcmF0aW8nLCAndV9ibHVyJywgJ3VfcGF0dGVybnNjYWxlX2EnLCAndV90ZXhfeV9hJywgJ3VfcGF0dGVybnNjYWxlX2InLCAndV90ZXhfeV9iJywgJ3VfaW1hZ2UnLCAndV9zZGZnYW1tYScsICd1X21peCddKTtcblxuICAgIHRoaXMuZG90U2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZG90JyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2l6ZScsICd1X2NvbG9yJywgJ3VfYmx1ciddKTtcblxuICAgIHRoaXMuc2RmU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignc2RmJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV9jb2xvcicsICd1X2dhbW1hJywgJ3VfYnVmZmVyJywgJ3Vfem9vbScsICd1X2ZhZGVkaXN0JywgJ3VfbWluZmFkZXpvb20nLCAndV9tYXhmYWRlem9vbScsICd1X2ZhZGV6b29tJywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLmljb25TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdpY29uJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV96b29tJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nLCAndV9vcGFjaXR5JywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLm91dGxpbmVTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdvdXRsaW5lJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InLCAndV93b3JsZCddXG4gICAgKTtcblxuICAgIHRoaXMucGF0dGVyblNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ3BhdHRlcm4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9wYXR0ZXJuX3RsX2EnLCAndV9wYXR0ZXJuX2JyX2EnLCAndV9wYXR0ZXJuX3RsX2InLCAndV9wYXR0ZXJuX2JyX2InLCAndV9taXgnLCAndV9wYXR0ZXJubWF0cml4X2EnLCAndV9wYXR0ZXJubWF0cml4X2InLCAndV9vcGFjaXR5JywgJ3VfaW1hZ2UnXVxuICAgICk7XG5cbiAgICB0aGlzLmZpbGxTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdmaWxsJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InXVxuICAgICk7XG5cbiAgICB0aGlzLmNvbGxpc2lvbkJveFNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2NvbGxpc2lvbmJveCcsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9leHRydWRlJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2NhbGUnLCAndV96b29tJywgJ3VfbWF4em9vbSddXG4gICAgKTtcblxuICAgIHRoaXMuaWRlbnRpdHlNYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuXG4gICAgLy8gVGhlIGJhY2tncm91bmRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gdGhlIGZ1bGwgKmNhbnZhcypcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUgPSAyO1xuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQgPSA0O1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCBuZXcgSW50MTZBcnJheShbLTEsIC0xLCAxLCAtMSwgLTEsIDEsIDEsIDFdKSwgZ2wuU1RBVElDX0RSQVcpO1xuXG4gICAgdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG5cbiAgICAvLyBUaGUgZGVidWdUZXh0QnVmZmVyIGlzIHVzZWQgdG8gZHJhdyB0aWxlIElEcyBmb3IgZGVidWdnaW5nXG4gICAgdGhpcy5kZWJ1Z1RleHRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnVGV4dEJ1ZmZlci5pdGVtU2l6ZSA9IDI7XG59O1xuXG4vKipcbiAqIFJlYmluZCB0aGUgbmVjZXNzYXJ5IGJ1ZmZlcnMgdG8gcmVuZGVyIGF0IGEgZGlmZmVyZW50IGV4dGVudCB0aGFuXG4gKiB0aGUgY3VycmVudCBvbmUuIE5vLW9wcyBpZiB0aGUgZXh0ZW50IGlzIG5vdCBjaGFuZ2luZy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbmV3RXh0ZW50XG4gKiBAZXhhbXBsZVxuICogdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG4gKi9cblBhaW50ZXIucHJvdG90eXBlLnNldEV4dGVudCA9IGZ1bmN0aW9uKG5ld0V4dGVudCkge1xuICAgIGlmICghbmV3RXh0ZW50IHx8IG5ld0V4dGVudCA9PT0gdGhpcy50aWxlRXh0ZW50KSByZXR1cm47XG5cbiAgICB0aGlzLnRpbGVFeHRlbnQgPSBuZXdFeHRlbnQ7XG5cbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgLy8gVGhlIHRpbGVFeHRlbnRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gYSBmdWxsICp0aWxlKlxuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlci5pdGVtU2l6ZSA9IDQ7XG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCA9IDQ7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudGlsZUV4dGVudEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShcbiAgICAgICAgZ2wuQVJSQVlfQlVGRkVSLFxuICAgICAgICBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICAvLyB0aWxlIGNvb3JkIHgsIHRpbGUgY29vcmQgeSwgdGV4dHVyZSBjb29yZCB4LCB0ZXh0dXJlIGNvb3JkIHlcbiAgICAgICAgICAgIDAsIDAsIDAsIDAsXG4gICAgICAgICAgICB0aGlzLnRpbGVFeHRlbnQsIDAsIDMyNzY3LCAwLFxuICAgICAgICAgICAgMCwgdGhpcy50aWxlRXh0ZW50LCAwLCAzMjc2NyxcbiAgICAgICAgICAgIHRoaXMudGlsZUV4dGVudCwgdGhpcy50aWxlRXh0ZW50LCAgMzI3NjcsIDMyNzY3XG4gICAgICAgIF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAvLyBUaGUgZGVidWdCdWZmZXIgaXMgdXNlZCB0byBkcmF3IHRpbGUgb3V0bGluZXMgZm9yIGRlYnVnZ2luZ1xuICAgIHRoaXMuZGVidWdCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1TaXplID0gMjtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1Db3VudCA9IDU7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuZGVidWdCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoXG4gICAgICAgIGdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgbmV3IEludDE2QXJyYXkoW1xuICAgICAgICAgICAgMCwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgMF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG59O1xuXG4vKlxuICogUmVzZXQgdGhlIGNvbG9yIGJ1ZmZlcnMgb2YgdGhlIGRyYXdpbmcgY2FudmFzLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5jbGVhckNvbG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5jbGVhckNvbG9yKDAsIDAsIDAsIDApO1xuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xufTtcblxuLypcbiAqIFJlc2V0IHRoZSBkcmF3aW5nIGNhbnZhcyBieSBjbGVhcmluZyB0aGUgc3RlbmNpbCBidWZmZXIgc28gdGhhdCB3ZSBjYW4gZHJhd1xuICogbmV3IHRpbGVzIGF0IHRoZSBzYW1lIGxvY2F0aW9uLCB3aGlsZSByZXRhaW5pbmcgcHJldmlvdXNseSBkcmF3biBwaXhlbHMuXG4gKi9cblBhaW50ZXIucHJvdG90eXBlLmNsZWFyU3RlbmNpbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhGRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdDbGlwcGluZ01hc2sgPSBmdW5jdGlvbih0aWxlKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5zd2l0Y2hTaGFkZXIodGhpcy5maWxsU2hhZGVyLCB0aWxlLnBvc01hdHJpeCk7XG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIENsZWFyIHRoZSBlbnRpcmUgc3RlbmNpbCBidWZmZXIsIGV4Y2VwdCBmb3IgdGhlIDd0aCBiaXQsIHdoaWNoIHN0b3Jlc1xuICAgIC8vIHRoZSBnbG9iYWwgY2xpcHBpbmcgbWFzayB0aGF0IGFsbG93cyB1cyB0byBhdm9pZCBkcmF3aW5nIGluIHJlZ2lvbnMgb2ZcbiAgICAvLyB0aWxlcyB3ZSd2ZSBhbHJlYWR5IHBhaW50ZWQgaW4uXG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhCRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIFRoZSBzdGVuY2lsIHRlc3Qgd2lsbCBmYWlsIGFsd2F5cywgbWVhbmluZyB3ZSBzZXQgYWxsIHBpeGVscyBjb3ZlcmVkXG4gICAgLy8gYnkgdGhpcyBnZW9tZXRyeSB0byAweDgwLiBXZSB1c2UgdGhlIGhpZ2hlc3QgYml0IDB4ODAgdG8gbWFyayB0aGUgcmVnaW9uc1xuICAgIC8vIHdlIHdhbnQgdG8gZHJhdyBpbi4gQWxsIHBpeGVscyB0aGF0IGhhdmUgdGhpcyBiaXQgKm5vdCogc2V0IHdpbGwgbmV2ZXIgYmVcbiAgICAvLyBkcmF3biBpbi5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHhDMCwgMHg0MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhDMCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLlJFUExBQ0UsIGdsLktFRVAsIGdsLktFRVApO1xuXG4gICAgLy8gRHJhdyB0aGUgY2xpcHBpbmcgbWFza1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgOCwgMCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLktFRVAsIGdsLktFRVAsIGdsLlJFUExBQ0UpO1xuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcbn07XG5cbi8vIE92ZXJyaWRkZW4gYnkgaGVhZGxlc3MgdGVzdHMuXG5QYWludGVyLnByb3RvdHlwZS5wcmVwYXJlQnVmZmVycyA9IGZ1bmN0aW9uKCkge307XG5QYWludGVyLnByb3RvdHlwZS5iaW5kRGVmYXVsdEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xufTtcblxudmFyIGRyYXcgPSB7XG4gICAgc3ltYm9sOiByZXF1aXJlKCcuL2RyYXdfc3ltYm9sJyksXG4gICAgbGluZTogcmVxdWlyZSgnLi9kcmF3X2xpbmUnKSxcbiAgICBmaWxsOiByZXF1aXJlKCcuL2RyYXdfZmlsbCcpLFxuICAgIHJhc3RlcjogcmVxdWlyZSgnLi9kcmF3X3Jhc3RlcicpLFxuICAgIGJhY2tncm91bmQ6IHJlcXVpcmUoJy4vZHJhd19iYWNrZ3JvdW5kJyksXG4gICAgZGVidWc6IHJlcXVpcmUoJy4vZHJhd19kZWJ1ZycpLFxuICAgIHZlcnRpY2VzOiByZXF1aXJlKCcuL2RyYXdfdmVydGljZXMnKVxufTtcblxuUGFpbnRlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24oc3R5bGUsIG9wdGlvbnMpIHtcbiAgICB0aGlzLnN0eWxlID0gc3R5bGU7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIHRoaXMubGluZUF0bGFzID0gc3R5bGUubGluZUF0bGFzO1xuXG4gICAgdGhpcy5zcHJpdGVBdGxhcyA9IHN0eWxlLnNwcml0ZUF0bGFzO1xuICAgIHRoaXMuc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHN0eWxlLnNwcml0ZSk7XG5cbiAgICB0aGlzLmdseXBoQXRsYXMgPSBzdHlsZS5nbHlwaEF0bGFzO1xuICAgIHRoaXMuZ2x5cGhBdGxhcy5iaW5kKHRoaXMuZ2wpO1xuXG4gICAgdGhpcy5mcmFtZUhpc3RvcnkucmVjb3JkKHRoaXMudHJhbnNmb3JtLnpvb20pO1xuXG4gICAgdGhpcy5wcmVwYXJlQnVmZmVycygpO1xuICAgIHRoaXMuY2xlYXJDb2xvcigpO1xuXG4gICAgZm9yICh2YXIgaSA9IHN0eWxlLl9ncm91cHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGdyb3VwID0gc3R5bGUuX2dyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHN0eWxlLnNvdXJjZXNbZ3JvdXAuc291cmNlXTtcblxuICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyU3RlbmNpbCgpO1xuICAgICAgICAgICAgc291cmNlLnJlbmRlcihncm91cCwgdGhpcyk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChncm91cC5zb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3TGF5ZXJzKGdyb3VwLCB0aGlzLmlkZW50aXR5TWF0cml4KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdUaWxlID0gZnVuY3Rpb24odGlsZSwgbGF5ZXJzKSB7XG4gICAgdGhpcy5zZXRFeHRlbnQodGlsZS50aWxlRXh0ZW50KTtcbiAgICB0aGlzLmRyYXdDbGlwcGluZ01hc2sodGlsZSk7XG4gICAgdGhpcy5kcmF3TGF5ZXJzKGxheWVycywgdGlsZS5wb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kZWJ1Zykge1xuICAgICAgICBkcmF3LmRlYnVnKHRoaXMsIHRpbGUpO1xuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdMYXllcnMgPSBmdW5jdGlvbihsYXllcnMsIG1hdHJpeCwgdGlsZSkge1xuICAgIGZvciAodmFyIGkgPSBsYXllcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5oaWRkZW4pXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBkcmF3W2xheWVyLnR5cGVdKHRoaXMsIGxheWVyLCBtYXRyaXgsIHRpbGUpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmVydGljZXMpIHtcbiAgICAgICAgICAgIGRyYXcudmVydGljZXModGhpcywgbGF5ZXIsIG1hdHJpeCwgdGlsZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBEcmF3cyBub24tb3BhcXVlIGFyZWFzLiBUaGlzIGlzIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG5QYWludGVyLnByb3RvdHlwZS5kcmF3U3RlbmNpbEJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHRoaXMuZmlsbFNoYWRlciwgdGhpcy5pZGVudGl0eU1hdHJpeCk7XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweDAwKTtcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG5cbiAgICAvLyBEcncgdGhlIGZpbGxpbmcgcXVhZCB3aGVyZSB0aGUgc3RlbmNpbCBidWZmZXIgaXNuJ3Qgc2V0LlxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wudW5pZm9ybTRmdih0aGlzLmZpbGxTaGFkZXIudV9jb2xvciwgWzAsIDAsIDAsIDAuNV0pO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59O1xuXG5QYWludGVyLnByb3RvdHlwZS50cmFuc2xhdGVNYXRyaXggPSBmdW5jdGlvbihtYXRyaXgsIHRpbGUsIHRyYW5zbGF0ZSwgYW5jaG9yKSB7XG4gICAgaWYgKCF0cmFuc2xhdGVbMF0gJiYgIXRyYW5zbGF0ZVsxXSkgcmV0dXJuIG1hdHJpeDtcblxuICAgIGlmIChhbmNob3IgPT09ICd2aWV3cG9ydCcpIHtcbiAgICAgICAgdmFyIHNpbkEgPSBNYXRoLnNpbigtdGhpcy50cmFuc2Zvcm0uYW5nbGUpO1xuICAgICAgICB2YXIgY29zQSA9IE1hdGguY29zKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHRyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVswXSAqIGNvc0EgLSB0cmFuc2xhdGVbMV0gKiBzaW5BLFxuICAgICAgICAgICAgdHJhbnNsYXRlWzBdICogc2luQSArIHRyYW5zbGF0ZVsxXSAqIGNvc0FcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICB2YXIgdGlsZVBpeGVsUmF0aW8gPSB0aGlzLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHRyYW5zbGF0aW9uID0gW1xuICAgICAgICB0cmFuc2xhdGVbMF0gLyB0aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdHJhbnNsYXRlWzFdIC8gdGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIDBcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBtYXQ0LnRyYW5zbGF0ZSh0cmFuc2xhdGVkTWF0cml4LCBtYXRyaXgsIHRyYW5zbGF0aW9uKTtcbiAgICByZXR1cm4gdHJhbnNsYXRlZE1hdHJpeDtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLnNhdmVUZXh0dXJlID0gZnVuY3Rpb24odGV4dHVyZSkge1xuICAgIHZhciB0ZXh0dXJlcyA9IHRoaXMucmV1c2FibGVUZXh0dXJlc1t0ZXh0dXJlLnNpemVdO1xuICAgIGlmICghdGV4dHVyZXMpIHtcbiAgICAgICAgdGhpcy5yZXVzYWJsZVRleHR1cmVzW3RleHR1cmUuc2l6ZV0gPSBbdGV4dHVyZV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHVyZXMucHVzaCh0ZXh0dXJlKTtcbiAgICB9XG59O1xuXG5cblBhaW50ZXIucHJvdG90eXBlLmdldFRleHR1cmUgPSBmdW5jdGlvbihzaXplKSB7XG4gICAgdmFyIHRleHR1cmVzID0gdGhpcy5yZXVzYWJsZVRleHR1cmVzW3NpemVdO1xuICAgIHJldHVybiB0ZXh0dXJlcyAmJiB0ZXh0dXJlcy5sZW5ndGggPiAwID8gdGV4dHVyZXMucG9wKCkgOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGdsaWZ5ID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBcImRlYnVnXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBmbG9hdCB1X3BvaW50c2l6ZTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcyxzdGVwKDMyNzY3LixhX3Bvcy54KSwxKTtnbF9Qb2ludFNpemU9dV9wb2ludHNpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZvaWQgbWFpbigpe2dsX0ZyYWdDb2xvcj11X2NvbG9yO31cIn0sXG4gICAgXCJkb3RcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBmbG9hdCB1X3NpemU7YXR0cmlidXRlIHZlYzIgYV9wb3M7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT11X3NpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3VuaWZvcm0gZmxvYXQgdV9ibHVyO3ZvaWQgbWFpbigpe2Zsb2F0IGEsYjthPWxlbmd0aChnbF9Qb2ludENvb3JkLS41KTtiPXNtb290aHN0ZXAoLjUsLjUtdV9ibHVyLGEpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmI7fVwifSxcbiAgICBcImZpbGxcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT0yLjt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXVfY29sb3I7fVwifSxcbiAgICBcImdhdXNzaWFuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X29mZnNldDt2YXJ5aW5nIHZlYzIgYVszXTt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dmVjMiBiPWdsX1Bvc2l0aW9uLnh5LzIuKy41O2FbMF09YjthWzFdPWIrdV9vZmZzZXQqMS4xODI0MjU1MjM4MDYzNTYzO2FbMl09Yi11X29mZnNldCoxLjE4MjQyNTUyMzgwNjM1NjM7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGFbM107dm9pZCBtYWluKCl7dmVjNCBiPXZlYzQoMCk7Yis9dGV4dHVyZTJEKHVfaW1hZ2UsYVswXSkqLjQwMjYxOTk0Njg5NDI0NzQ2O2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMV0pKi4yOTg2OTAwMjY1NTI4NzYzO2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMl0pKi4yOTg2OTAwMjY1NTI4NzYzO2dsX0ZyYWdDb2xvcj1iO31cIn0sXG4gICAgXCJsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW8sdV9leHRyYTt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGg7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBtYXQyIHVfYW50aWFsaWFzaW5nbWF0cml4O3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxlO2Q9YV9kYXRhLnh5O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTt2ZWM0IGY9dmVjNCh1X2xpbmV3aWR0aC5zKmQqLjAxNTg3MzAxNiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoZmxvb3IoYV9wb3MqLjUpK2YueHkvdV9yYXRpbywwLDEpO2Zsb2F0IGcsaCxpO2c9Z2xfUG9zaXRpb24ueS9nbF9Qb3NpdGlvbi53O2g9bGVuZ3RoKGQpL2xlbmd0aCh1X2FudGlhbGlhc2luZ21hdHJpeCpkKTtpPTEuLygxLi1nKnVfZXh0cmEpO2M9aSpoO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGgsdV9kYXNoYXJyYXk7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2JsdXI7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiLGM7dm9pZCBtYWluKCl7ZmxvYXQgZCxlLGY7ZD1sZW5ndGgoYSkqdV9saW5ld2lkdGgucztlPXVfYmx1cipjO2Y9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtZSksdV9saW5ld2lkdGgucy1kKS9lLDAuLDEuKTtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJsaW5lcGF0dGVyblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW87dW5pZm9ybSB2ZWMyIHVfbGluZXdpZHRoO3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZSxmLGc7Yz1hX2RhdGEueHk7ZmxvYXQgZD1hX2RhdGEueioxMjguK2FfZGF0YS53O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTtmPWMqLjAxNTg3MzAxNjtnPXVfbGluZXdpZHRoLnMqZjtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPWQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5fc2l6ZV9hLHVfcGF0dGVybl9zaXplX2IsdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBmbG9hdCB1X3BvaW50LHVfYmx1cix1X2ZhZGUsdV9vcGFjaXR5O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiO3ZvaWQgbWFpbigpe2Zsb2F0IGMsZCxlLGYsZyxoO2M9bGVuZ3RoKGEpKnVfbGluZXdpZHRoLnM7ZD1jbGFtcChtaW4oYy0odV9saW5ld2lkdGgudC11X2JsdXIpLHVfbGluZXdpZHRoLnMtYykvdV9ibHVyLDAuLDEuKTtlPW1vZChiL3VfcGF0dGVybl9zaXplX2EueCwxLik7Zj1tb2QoYi91X3BhdHRlcm5fc2l6ZV9iLngsMS4pO2c9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYS55O2g9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYi55O3ZlYzIgaSxqO2k9bWl4KHVfcGF0dGVybl90bF9hLHVfcGF0dGVybl9icl9hLHZlYzIoZSxnKSk7aj1taXgodV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2IsdmVjMihmLGgpKTt2ZWM0IGs9bWl4KHRleHR1cmUyRCh1X2ltYWdlLGkpLHRleHR1cmUyRCh1X2ltYWdlLGopLHVfZmFkZSk7ZCo9dV9vcGFjaXR5O2dsX0ZyYWdDb2xvcj1rKmQ7fVwifSxcbiAgICBcImxpbmVzZGZwYXR0ZXJuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5zY2FsZV9hLHVfcGF0dGVybnNjYWxlX2I7dW5pZm9ybSBmbG9hdCB1X3JhdGlvLHVfdGV4X3lfYSx1X3RleF95X2I7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxmO2Q9YV9kYXRhLnh5O2Zsb2F0IGU9YV9kYXRhLnoqMTI4LithX2RhdGEudztmPW1vZChhX3BvcywyLik7Zi55PXNpZ24oZi55LS41KTthPWY7dmVjNCBnPXZlYzQodV9saW5ld2lkdGgucypkKi4wMTU4NzMwMTYsMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPXZlYzIoZSp1X3BhdHRlcm5zY2FsZV9hLngsZi55KnVfcGF0dGVybnNjYWxlX2EueSt1X3RleF95X2EpO2M9dmVjMihlKnVfcGF0dGVybnNjYWxlX2IueCxmLnkqdV9wYXR0ZXJuc2NhbGVfYi55K3VfdGV4X3lfYik7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDt1bmlmb3JtIHZlYzQgdV9jb2xvcjt1bmlmb3JtIGZsb2F0IHVfYmx1cix1X3NkZmdhbW1hLHVfbWl4O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmLGcsaDtkPWxlbmd0aChhKSp1X2xpbmV3aWR0aC5zO2U9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtdV9ibHVyKSx1X2xpbmV3aWR0aC5zLWQpL3VfYmx1ciwwLiwxLik7Zj10ZXh0dXJlMkQodV9pbWFnZSxiKS5hO2c9dGV4dHVyZTJEKHVfaW1hZ2UsYykuYTtoPW1peChmLGcsdV9taXgpO2UqPXNtb290aHN0ZXAoLjUtdV9zZGZnYW1tYSwuNSt1X3NkZmdhbW1hLGgpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmU7fVwifSxcbiAgICBcIm91dGxpbmVcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfd29ybGQ7dmFyeWluZyB2ZWMyIGE7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4pLzIuKnVfd29ybGQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZvaWQgbWFpbigpe2Zsb2F0IGIsYztiPWxlbmd0aChhLWdsX0ZyYWdDb29yZC54eSk7Yz1zbW9vdGhzdGVwKDEuLDAuLGIpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmM7fVwifSxcbiAgICBcInBhdHRlcm5cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBtYXQzIHVfcGF0dGVybm1hdHJpeF9hLHVfcGF0dGVybm1hdHJpeF9iO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KHVfcGF0dGVybm1hdHJpeF9hKnZlYzMoYV9wb3MsMSkpLnh5O2I9KHVfcGF0dGVybm1hdHJpeF9iKnZlYzMoYV9wb3MsMSkpLnh5O31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIGZsb2F0IHVfb3BhY2l0eSx1X21peDt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgYSxiO3ZvaWQgbWFpbigpe3ZlYzIgYyxkLGYsZztjPW1vZChhLDEuKTtkPW1peCh1X3BhdHRlcm5fdGxfYSx1X3BhdHRlcm5fYnJfYSxjKTt2ZWM0IGUsaDtlPXRleHR1cmUyRCh1X2ltYWdlLGQpO2Y9bW9kKGIsMS4pO2c9bWl4KHVfcGF0dGVybl90bF9iLHVfcGF0dGVybl9icl9iLGYpO2g9dGV4dHVyZTJEKHVfaW1hZ2UsZyk7Z2xfRnJhZ0NvbG9yPW1peChlLGgsdV9taXgpKnVfb3BhY2l0eTt9XCJ9LFxuICAgIFwicmFzdGVyXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3RsX3BhcmVudDt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfcGFyZW50LHVfYnVmZmVyX3NjYWxlO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfdGV4dHVyZV9wb3M7dmFyeWluZyB2ZWMyIGEsYjt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7YT0oYV90ZXh0dXJlX3Bvcy8zMjc2Ny4tLjUpL3VfYnVmZmVyX3NjYWxlKy41O2I9YSp1X3NjYWxlX3BhcmVudCt1X3RsX3BhcmVudDt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X29wYWNpdHkwLHVfb3BhY2l0eTEsdV9icmlnaHRuZXNzX2xvdyx1X2JyaWdodG5lc3NfaGlnaCx1X3NhdHVyYXRpb25fZmFjdG9yLHVfY29udHJhc3RfZmFjdG9yO3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2UwLHVfaW1hZ2UxO3ZhcnlpbmcgdmVjMiBhLGI7dW5pZm9ybSB2ZWMzIHVfc3Bpbl93ZWlnaHRzO3ZvaWQgbWFpbigpe3ZlYzQgYyxkLGU7Yz10ZXh0dXJlMkQodV9pbWFnZTAsYSk7ZD10ZXh0dXJlMkQodV9pbWFnZTEsYik7ZT1jKnVfb3BhY2l0eTArZCp1X29wYWNpdHkxO3ZlYzMgZixoLGk7Zj1lLnJnYjtmPXZlYzMoZG90KGYsdV9zcGluX3dlaWdodHMueHl6KSxkb3QoZix1X3NwaW5fd2VpZ2h0cy56eHkpLGRvdChmLHVfc3Bpbl93ZWlnaHRzLnl6eCkpO2Zsb2F0IGc9KGUucitlLmcrZS5iKS8zLjtmKz0oZy1mKSp1X3NhdHVyYXRpb25fZmFjdG9yO2Y9KGYtLjUpKnVfY29udHJhc3RfZmFjdG9yKy41O2g9dmVjMyh1X2JyaWdodG5lc3NfbG93KTtpPXZlYzModV9icmlnaHRuZXNzX2hpZ2gpO2dsX0ZyYWdDb2xvcj12ZWM0KG1peChoLGksZiksZS5hKTt9XCJ9LFxuICAgIFwiaWNvblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfb2Zmc2V0O2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTEsYV9kYXRhMjt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfem9vbSx1X2ZhZGVkaXN0LHVfbWluZmFkZXpvb20sdV9tYXhmYWRlem9vbSx1X2ZhZGV6b29tLHVfb3BhY2l0eSx1X2V4dHJhO3VuaWZvcm0gYm9vbCB1X3NrZXdlZDt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZTtjPWFfZGF0YTEueHk7ZmxvYXQgZCxmLGcsaCxpLGo7ZD1hX2RhdGExWzJdO2U9YV9kYXRhMi5zdDtmPWVbMF07Zz1lWzFdO2g9MTAuO2k9Mi4tc3RlcChmLHVfem9vbSktKDEuLXN0ZXAoZyx1X3pvb20pKTtqPWNsYW1wKCh1X2ZhZGV6b29tLWQpL3VfZmFkZWRpc3QsMC4sMS4pO2lmKHVfZmFkZWRpc3Q+PTAuKWI9ajtlbHNlIGI9MS4tajtpZih1X21heGZhZGV6b29tPGQpYj0wLjtpZih1X21pbmZhZGV6b29tPj1kKWI9MS47aSs9c3RlcChiLDAuKTtpZih1X3NrZXdlZCl7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4sMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zK2sueHksMCwxKTtnbF9Qb3NpdGlvbi56Kz1pKmdsX1Bvc2l0aW9uLnc7fWVsc2V7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4saSwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSkrazt9YT1jL3VfdGV4c2l6ZTtiKj11X29wYWNpdHk7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGI7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXRleHR1cmUyRCh1X3RleHR1cmUsYSkqYjt9XCJ9LFxuICAgIFwic2RmXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3MsYV9vZmZzZXQ7YXR0cmlidXRlIHZlYzQgYV9kYXRhMSxhX2RhdGEyO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gZmxvYXQgdV96b29tLHVfZmFkZWRpc3QsdV9taW5mYWRlem9vbSx1X21heGZhZGV6b29tLHVfZmFkZXpvb20sdV9leHRyYTt1bmlmb3JtIGJvb2wgdV9za2V3ZWQ7dW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGIsYzt2b2lkIG1haW4oKXt2ZWMyIGQsZjtkPWFfZGF0YTEueHk7ZmxvYXQgZSxnLGgsaSxqLGssbDtlPWFfZGF0YTFbMl07Zj1hX2RhdGEyLnN0O2c9ZlswXTtoPWZbMV07aT0yLi1zdGVwKGcsdV96b29tKS0oMS4tc3RlcChoLHVfem9vbSkpO2o9Y2xhbXAoKHVfZmFkZXpvb20tZSkvdV9mYWRlZGlzdCwwLiwxLik7aWYodV9mYWRlZGlzdD49MC4pYj1qO2Vsc2UgYj0xLi1qO2lmKHVfbWF4ZmFkZXpvb208ZSliPTAuO2lmKHVfbWluZmFkZXpvb20+PWUpYj0xLjtpKz1zdGVwKGIsMC4pO2lmKHVfc2tld2VkKXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3Mray54eSwwLDEpO2dsX1Bvc2l0aW9uLnorPWkqZ2xfUG9zaXRpb24udzt9ZWxzZXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LixpLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKStrO31rPWdsX1Bvc2l0aW9uLnkvZ2xfUG9zaXRpb24udztsPTEuLygxLi1rKnVfZXh0cmEpO2M9bDthPWQvdV90ZXhzaXplO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHNhbXBsZXIyRCB1X3RleHR1cmU7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2J1ZmZlcix1X2dhbW1hO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmO2Q9dV9nYW1tYSpjO2U9dGV4dHVyZTJEKHVfdGV4dHVyZSxhKS5hO2Y9c21vb3Roc3RlcCh1X2J1ZmZlci1kLHVfYnVmZmVyK2QsZSkqYjtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJjb2xsaXNpb25ib3hcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3BvcyxhX2V4dHJ1ZGUsYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfc2NhbGU7dmFyeWluZyBmbG9hdCBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcythX2V4dHJ1ZGUvdV9zY2FsZSwwLDEpO2E9YV9kYXRhLng7Yj1hX2RhdGEueTt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X3pvb20sdV9tYXh6b29tO3ZhcnlpbmcgZmxvYXQgYSxiO3ZvaWQgbWFpbigpe2Zsb2F0IGM9LjU7Z2xfRnJhZ0NvbG9yPXZlYzQoMCwxLDAsMSkqYztpZihiPnVfem9vbSlnbF9GcmFnQ29sb3I9dmVjNCgxLDAsMCwxKSpjO2lmKHVfem9vbT49YSlnbF9GcmFnQ29sb3I9dmVjNCgwLDAsMCwxKSpjKi4yNTtpZihiPj11X21heHpvb20pZ2xfRnJhZ0NvbG9yPXZlYzQoMCwwLDEsMSkqYyouMjt9XCJ9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQnKTtcbnZhciBUaWxlUHlyYW1pZCA9IHJlcXVpcmUoJy4vdGlsZV9weXJhbWlkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcbnZhciB1cmxSZXNvbHZlID0gcmVxdWlyZSgncmVzb2x2ZS11cmwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHZW9KU09OU291cmNlO1xuXG4vKipcbiAqIENyZWF0ZSBhIEdlb0pTT04gZGF0YSBzb3VyY2UgaW5zdGFuY2UgZ2l2ZW4gYW4gb3B0aW9ucyBvYmplY3RcbiAqIEBjbGFzcyBHZW9KU09OU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IG9wdGlvbnMuZGF0YSBBIEdlb0pTT04gZGF0YSBvYmplY3Qgb3IgVVJMIHRvIGl0LiBUaGUgbGF0dGVyIGlzIHByZWZlcmFibGUgaW4gY2FzZSBvZiBsYXJnZSBHZW9KU09OIGZpbGVzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heHpvb209MTRdIE1heGltdW0gem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgYXQuXG4gKiBAZXhhbXBsZVxuICogdmFyIHNvdXJjZU9iaiA9IG5ldyBtYXBib3hnbC5HZW9KU09OU291cmNlKHtcbiAqICAgIGRhdGE6IHtcbiAqICAgICAgICBcInR5cGVcIjogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICogICAgICAgIFwiZmVhdHVyZXNcIjogW3tcbiAqICAgICAgICAgICAgXCJ0eXBlXCI6IFwiRmVhdHVyZVwiLFxuICogICAgICAgICAgICBcImdlb21ldHJ5XCI6IHtcbiAqICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIlBvaW50XCIsXG4gKiAgICAgICAgICAgICAgICBcImNvb3JkaW5hdGVzXCI6IFtcbiAqICAgICAgICAgICAgICAgICAgICAtNzYuNTMwNjMyOTcyNzE3MjksXG4gKiAgICAgICAgICAgICAgICAgICAgMzkuMTgxNzQwNzc5OTQxMDhcbiAqICAgICAgICAgICAgICAgIF1cbiAqICAgICAgICAgICAgfVxuICogICAgICAgIH1dXG4gKiAgICB9XG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBHZW9KU09OU291cmNlKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIHRoaXMuX2RhdGEgPSBvcHRpb25zLmRhdGE7XG5cbiAgICBpZiAob3B0aW9ucy5tYXh6b29tICE9PSB1bmRlZmluZWQpIHRoaXMubWF4em9vbSA9IG9wdGlvbnMubWF4em9vbTtcblxuICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICB0aWxlU2l6ZTogNTEyLFxuICAgICAgICBtaW56b29tOiB0aGlzLm1pbnpvb20sXG4gICAgICAgIG1heHpvb206IHRoaXMubWF4em9vbSxcbiAgICAgICAgY2FjaGVTaXplOiAyMCxcbiAgICAgICAgbG9hZDogdGhpcy5fbG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICB1bmxvYWQ6IHRoaXMuX3VubG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWRkOiB0aGlzLl9hZGRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpXG4gICAgfSk7XG59XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEV2ZW50ZWQsIC8qKiBAbGVuZHMgR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUgKi97XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAxNCxcbiAgICBfZGlydHk6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgc291cmNlIGdlb2pzb24gZGF0YSBhbmQgcmVyZW5kZXIgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGRhdGEgQSBHZW9KU09OIGRhdGEgb2JqZWN0IG9yIFVSTCB0byBpdC4gVGhlIGxhdHRlciBpcyBwcmVmZXJhYmxlIGluIGNhc2Ugb2YgbGFyZ2UgR2VvSlNPTiBmaWxlcy5cbiAgICAgKiBAcmV0dXJucyB7R2VvSlNPTlNvdXJjZX0gdGhpc1xuICAgICAqL1xuICAgIHNldERhdGE6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScpO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcClcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHRoaXMubWFwLnRyYW5zZm9ybSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkZWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX2RpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEYXRhKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVuZGVyOiBTb3VyY2UuX3JlbmRlclRpbGVzLFxuICAgIGZlYXR1cmVzQXQ6IFNvdXJjZS5fdmVjdG9yRmVhdHVyZXNBdCxcblxuICAgIF91cGRhdGVEYXRhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkYXRhID0gdXJsUmVzb2x2ZSh3aW5kb3cubG9jYXRpb24uaHJlZiwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdwYXJzZSBnZW9qc29uJywge1xuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHRpbGVTaXplOiA1MTIsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb21cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyKSB7XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcblxuICAgICAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuXG4gICAgX2xvYWRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUuY29vcmQueiA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHRpbGUuY29vcmQueiAtIHRoaXMubWF4em9vbSkgOiAxO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgdWlkOiB0aWxlLnVpZCxcbiAgICAgICAgICAgIGNvb3JkOiB0aWxlLmNvb3JkLFxuICAgICAgICAgICAgem9vbTogdGlsZS5jb29yZC56LFxuICAgICAgICAgICAgbWF4Wm9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgdGlsZVNpemU6IDUxMixcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5pZCxcbiAgICAgICAgICAgIG92ZXJzY2FsaW5nOiBvdmVyc2NhbGluZyxcbiAgICAgICAgICAgIGFuZ2xlOiB0aGlzLm1hcC50cmFuc2Zvcm0uYW5nbGUsXG4gICAgICAgICAgICBwaXRjaDogdGhpcy5tYXAudHJhbnNmb3JtLnBpdGNoLFxuICAgICAgICAgICAgY29sbGlzaW9uRGVidWc6IHRoaXMubWFwLmNvbGxpc2lvbkRlYnVnXG4gICAgICAgIH07XG5cbiAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIGdlb2pzb24gdGlsZScsIHBhcmFtcywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG5cbiAgICAgICAgICAgIHRpbGUudW5sb2FkVmVjdG9yRGF0YSh0aGlzLm1hcC5wYWludGVyKTtcblxuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGlsZS5sb2FkVmVjdG9yRGF0YShkYXRhKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5sb2FkJywge3RpbGU6IHRpbGV9KTtcblxuICAgICAgICB9LmJpbmQodGhpcyksIHRoaXMud29ya2VySUQpO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCd2ZWN0b3ItdGlsZScpLlZlY3RvclRpbGVGZWF0dXJlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlb0pTT05XcmFwcGVyO1xuXG4vLyBjb25mb3JtIHRvIHZlY3RvcnRpbGUgYXBpXG5mdW5jdGlvbiBHZW9KU09OV3JhcHBlcihmZWF0dXJlcykge1xuICAgIHRoaXMuZmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICB0aGlzLmxlbmd0aCA9IGZlYXR1cmVzLmxlbmd0aDtcbn1cblxuR2VvSlNPTldyYXBwZXIucHJvdG90eXBlLmZlYXR1cmUgPSBmdW5jdGlvbihpKSB7XG4gICAgcmV0dXJuIG5ldyBGZWF0dXJlV3JhcHBlcih0aGlzLmZlYXR1cmVzW2ldKTtcbn07XG5cbmZ1bmN0aW9uIEZlYXR1cmVXcmFwcGVyKGZlYXR1cmUpIHtcbiAgICB0aGlzLnR5cGUgPSBmZWF0dXJlLnR5cGU7XG4gICAgdGhpcy5yYXdHZW9tZXRyeSA9IGZlYXR1cmUudHlwZSA9PT0gMSA/IFtmZWF0dXJlLmdlb21ldHJ5XSA6IGZlYXR1cmUuZ2VvbWV0cnk7XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gZmVhdHVyZS50YWdzO1xuICAgIHRoaXMuZXh0ZW50ID0gNDA5Njtcbn1cblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByaW5ncyA9IHRoaXMucmF3R2VvbWV0cnk7XG4gICAgdGhpcy5nZW9tZXRyeSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmluZyA9IHJpbmdzW2ldLFxuICAgICAgICAgICAgbmV3UmluZyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG5ld1JpbmcucHVzaChuZXcgUG9pbnQocmluZ1tqXVswXSwgcmluZ1tqXVsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2VvbWV0cnkucHVzaChuZXdSaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnk7XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5nZW9tZXRyeSkgdGhpcy5sb2FkR2VvbWV0cnkoKTtcblxuICAgIHZhciByaW5ncyA9IHRoaXMuZ2VvbWV0cnksXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjb29yZCA9IHJpbmdbal07XG5cbiAgICAgICAgICAgIHgxID0gTWF0aC5taW4oeDEsIGNvb3JkLngpO1xuICAgICAgICAgICAgeDIgPSBNYXRoLm1heCh4MiwgY29vcmQueCk7XG4gICAgICAgICAgICB5MSA9IE1hdGgubWluKHkxLCBjb29yZC55KTtcbiAgICAgICAgICAgIHkyID0gTWF0aC5tYXgoeTIsIGNvb3JkLnkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4MSwgeTEsIHgyLCB5Ml07XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUudG9HZW9KU09OID0gVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlJyk7XG52YXIgbm9ybWFsaXplVVJMID0gcmVxdWlyZSgnLi4vdXRpbC9tYXBib3gnKS5ub3JtYWxpemVUaWxlVVJMO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhc3RlclRpbGVTb3VyY2U7XG5cbmZ1bmN0aW9uIFJhc3RlclRpbGVTb3VyY2Uob3B0aW9ucykge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHV0aWwucGljayhvcHRpb25zLCBbJ3VybCcsICd0aWxlU2l6ZSddKSk7XG5cbiAgICBTb3VyY2UuX2xvYWRUaWxlSlNPTi5jYWxsKHRoaXMsIG9wdGlvbnMpO1xufVxuXG5SYXN0ZXJUaWxlU291cmNlLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChFdmVudGVkLCB7XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAyMixcbiAgICB0aWxlU2l6ZTogNTEyLFxuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB9LFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3B5cmFtaWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX3B5cmFtaWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5cmFtaWQudXBkYXRlKHRoaXMudXNlZCwgdHJhbnNmb3JtLCB0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcblxuICAgIF9sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBhamF4LmdldEltYWdlKG5vcm1hbGl6ZVVSTCh0aWxlLmNvb3JkLnVybCh0aGlzLnRpbGVzKSwgdGhpcy51cmwpLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGdsID0gdGhpcy5tYXAucGFpbnRlci5nbDtcbiAgICAgICAgICAgIHRpbGUudGV4dHVyZSA9IHRoaXMubWFwLnBhaW50ZXIuZ2V0VGV4dHVyZShpbWcud2lkdGgpO1xuICAgICAgICAgICAgaWYgKHRpbGUudGV4dHVyZSkge1xuICAgICAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRpbGUudGV4dHVyZSk7XG4gICAgICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCAwLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aWxlLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSX01JUE1BUF9ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGltZyk7XG4gICAgICAgICAgICAgICAgdGlsZS50ZXh0dXJlLnNpemUgPSBpbWcud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnbC5nZW5lcmF0ZU1pcG1hcChnbC5URVhUVVJFXzJEKTtcblxuICAgICAgICAgICAgdGlsZS50aW1lQWRkZWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHRoaXMubWFwLmFuaW1hdGlvbkxvb3Auc2V0KHRoaXMuc3R5bGUucmFzdGVyRmFkZUR1cmF0aW9uKTtcblxuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGlsZS5sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUubG9hZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9hYm9ydFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS5hYm9ydGVkID0gdHJ1ZTtcbiAgICB9LFxuXG4gICAgX2FkZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmFkZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmVUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5yZW1vdmUnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfdW5sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBpZiAodGlsZS50ZXh0dXJlKSB0aGlzLm1hcC5wYWludGVyLnNhdmVUZXh0dXJlKHRpbGUudGV4dHVyZSk7XG4gICAgfSxcblxuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFRpbGVQeXJhbWlkID0gcmVxdWlyZSgnLi90aWxlX3B5cmFtaWQnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBub3JtYWxpemVVUkwgPSByZXF1aXJlKCcuLi91dGlsL21hcGJveCcpLm5vcm1hbGl6ZVNvdXJjZVVSTDtcblxuZXhwb3J0cy5fbG9hZFRpbGVKU09OID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciBsb2FkZWQgPSBmdW5jdGlvbihlcnIsIHRpbGVKU09OKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKHRpbGVKU09OLFxuICAgICAgICAgICAgWyd0aWxlcycsICdtaW56b29tJywgJ21heHpvb20nLCAnYXR0cmlidXRpb24nXSkpO1xuXG4gICAgICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICAgICAgdGlsZVNpemU6IHRoaXMudGlsZVNpemUsXG4gICAgICAgICAgICBjYWNoZVNpemU6IDIwLFxuICAgICAgICAgICAgbWluem9vbTogdGhpcy5taW56b29tLFxuICAgICAgICAgICAgbWF4em9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgcmVwYXJzZU92ZXJzY2FsZWQ6IHRoaXMucmVwYXJzZU92ZXJzY2FsZWQsXG4gICAgICAgICAgICBsb2FkOiB0aGlzLl9sb2FkVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgdW5sb2FkOiB0aGlzLl91bmxvYWRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgICAgICBhZGQ6IHRoaXMuX2FkZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcmVkb1BsYWNlbWVudDogdGhpcy5fcmVkb1RpbGVQbGFjZW1lbnQgPyB0aGlzLl9yZWRvVGlsZVBsYWNlbWVudC5iaW5kKHRoaXMpIDogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmlyZSgnbG9hZCcpO1xuICAgIH0uYmluZCh0aGlzKTtcblxuICAgIGlmIChvcHRpb25zLnVybCkge1xuICAgICAgICBhamF4LmdldEpTT04obm9ybWFsaXplVVJMKG9wdGlvbnMudXJsKSwgbG9hZGVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBicm93c2VyLmZyYW1lKGxvYWRlZC5iaW5kKHRoaXMsIG51bGwsIG9wdGlvbnMpKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl9yZW5kZXJUaWxlcyA9IGZ1bmN0aW9uKGxheWVycywgcGFpbnRlcikge1xuICAgIGlmICghdGhpcy5fcHlyYW1pZClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQucmVuZGVyZWRJRHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3B5cmFtaWQuZ2V0VGlsZShpZHNbaV0pLFxuICAgICAgICAgICAgLy8gY29vcmQgaXMgZGlmZmVyZW50IHRoYW4gdGlsZS5jb29yZCBmb3Igd3JhcHBlZCB0aWxlcyBzaW5jZSB0aGUgYWN0dWFsXG4gICAgICAgICAgICAvLyB0aWxlIG9iamVjdCBpcyBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlIHZpc2libGUgY29waWVzIG9mIHRoYXQgdGlsZS5cbiAgICAgICAgICAgIGNvb3JkID0gVGlsZUNvb3JkLmZyb21JRChpZHNbaV0pLFxuICAgICAgICAgICAgeiA9IGNvb3JkLnosXG4gICAgICAgICAgICB4ID0gY29vcmQueCxcbiAgICAgICAgICAgIHkgPSBjb29yZC55LFxuICAgICAgICAgICAgdyA9IGNvb3JkLnc7XG5cbiAgICAgICAgLy8gaWYgeiA+IG1heHpvb20gdGhlbiB0aGUgdGlsZSBpcyBhY3R1YWxseSBhIG92ZXJzY2FsZWQgbWF4em9vbSB0aWxlLFxuICAgICAgICAvLyBzbyBjYWxjdWxhdGUgdGhlIG1hdHJpeCB0aGUgbWF4em9vbSB0aWxlIHdvdWxkIHVzZS5cbiAgICAgICAgeiA9IE1hdGgubWluKHosIHRoaXMubWF4em9vbSk7XG5cbiAgICAgICAgeCArPSB3ICogKDEgPDwgeik7XG4gICAgICAgIHRpbGUuY2FsY3VsYXRlTWF0cmljZXMoeiwgeCwgeSwgcGFpbnRlci50cmFuc2Zvcm0sIHBhaW50ZXIpO1xuXG4gICAgICAgIHBhaW50ZXIuZHJhd1RpbGUodGlsZSwgbGF5ZXJzKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl92ZWN0b3JGZWF0dXJlc0F0ID0gZnVuY3Rpb24oY29vcmQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuX3B5cmFtaWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBbXSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gdGhpcy5fcHlyYW1pZC50aWxlQXQoY29vcmQpO1xuICAgIGlmICghcmVzdWx0KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuXG4gICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3F1ZXJ5IGZlYXR1cmVzJywge1xuICAgICAgICB1aWQ6IHJlc3VsdC50aWxlLnVpZCxcbiAgICAgICAgeDogcmVzdWx0LngsXG4gICAgICAgIHk6IHJlc3VsdC55LFxuICAgICAgICBzY2FsZTogcmVzdWx0LnNjYWxlLFxuICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfSwgY2FsbGJhY2ssIHJlc3VsdC50aWxlLndvcmtlcklEKTtcbn07XG5cbi8qXG4gKiBDcmVhdGUgYSB0aWxlZCBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50eXBlIEVpdGhlciBgcmFzdGVyYCBvciBgdmVjdG9yYC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCBBIHRpbGUgc291cmNlIFVSTC4gVGhpcyBzaG91bGQgZWl0aGVyIGJlIGBtYXBib3g6Ly97bWFwaWR9YCBvciBhIGZ1bGwgYGh0dHBbc11gIHVybCB0aGF0IHBvaW50cyB0byBhIFRpbGVKU09OIGVuZHBvaW50LlxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy50aWxlcyBBbiBhcnJheSBvZiB0aWxlIHNvdXJjZXMuIElmIGB1cmxgIGlzIG5vdCBzcGVjaWZpZWQsIGB0aWxlc2AgY2FuIGJlIHVzZWQgaW5zdGVhZCB0byBzcGVjaWZ5IHRpbGUgc291cmNlcywgYXMgaW4gdGhlIFRpbGVKU09OIHNwZWMuIE90aGVyIFRpbGVKU09OIGtleXMgc3VjaCBhcyBgbWluem9vbWAgYW5kIGBtYXh6b29tYCBjYW4gYmUgc3BlY2lmaWVkIGluIGEgc291cmNlIG9iamVjdCBpZiBgdGlsZXNgIGlzIHVzZWQuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5pZCBBbiBvcHRpb25hbCBgaWRgIHRvIGFzc2lnbiB0byB0aGUgc291cmNlXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGlsZVNpemU9NTEyXSBPcHRpb25hbCB0aWxlIHNpemUgKHdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzLCBhc3N1bWluZyB0aWxlcyBhcmUgc3F1YXJlKS4gVGhpcyBvcHRpb24gaXMgb25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBzb3VyY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5jYWNoZVNpemUgT3B0aW9uYWwgbWF4IG51bWJlciBvZiB0aWxlcyB0byBjYWNoZSBhdCBhbnkgZ2l2ZW4gdGltZVxuICogQGV4YW1wbGVcbiAqIHZhciBzb3VyY2VPYmogPSBuZXcgbWFwYm94Z2wuU291cmNlLmNyZWF0ZSh7XG4gKiAgICB0eXBlOiAndmVjdG9yJyxcbiAqICAgIHVybDogJ21hcGJveDovL21hcGJveC5tYXBib3gtc3RyZWV0cy12NSdcbiAqIH0pO1xuICogbWFwLmFkZFNvdXJjZSgnc29tZSBpZCcsIHNvdXJjZU9iaik7IC8vIGFkZFxuICogbWFwLnJlbW92ZVNvdXJjZSgnc29tZSBpZCcpOyAgLy8gcmVtb3ZlXG4gKi9cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24oc291cmNlKSB7XG4gICAgLy8gVGhpcyBpcyBub3QgYXQgZmlsZSBzY29wZSBpbiBvcmRlciB0byBhdm9pZCBhIGNpcmN1bGFyIHJlcXVpcmUuXG4gICAgdmFyIHNvdXJjZXMgPSB7XG4gICAgICAgIHZlY3RvcjogcmVxdWlyZSgnLi92ZWN0b3JfdGlsZV9zb3VyY2UnKSxcbiAgICAgICAgcmFzdGVyOiByZXF1aXJlKCcuL3Jhc3Rlcl90aWxlX3NvdXJjZScpLFxuICAgICAgICBnZW9qc29uOiByZXF1aXJlKCcuL2dlb2pzb25fc291cmNlJyksXG4gICAgICAgIHZpZGVvOiByZXF1aXJlKCcuL3ZpZGVvX3NvdXJjZScpXG4gICAgfTtcblxuICAgIGZvciAodmFyIHR5cGUgaW4gc291cmNlcykge1xuICAgICAgICBpZiAoc291cmNlIGluc3RhbmNlb2Ygc291cmNlc1t0eXBlXSkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgc291cmNlc1tzb3VyY2UudHlwZV0oc291cmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpO1xudmFyIG1hdDIgPSBnbG1hdHJpeC5tYXQyO1xudmFyIG1hdDQgPSBnbG1hdHJpeC5tYXQ0O1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXJTZXQgPSByZXF1aXJlKCcuLi9kYXRhL2J1ZmZlci9idWZmZXJfc2V0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZTtcblxuLyoqXG4gKiBBIHRpbGUgb2JqZWN0IGlzIHRoZSBjb21iaW5hdGlvbiBvZiBhIENvb3JkaW5hdGUsIHdoaWNoIGRlZmluZXNcbiAqIGl0cyBwbGFjZSwgYXMgd2VsbCBhcyBhIHVuaXF1ZSBJRCBhbmQgZGF0YSB0cmFja2luZyBmb3IgaXRzIGNvbnRlbnRcbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZVxuICovXG5mdW5jdGlvbiBUaWxlKGNvb3JkLCBzaXplKSB7XG4gICAgdGhpcy5jb29yZCA9IGNvb3JkO1xuICAgIHRoaXMudWlkID0gdXRpbC51bmlxdWVJZCgpO1xuICAgIHRoaXMubG9hZGVkID0gZmFsc2U7XG4gICAgdGhpcy51c2VzID0gMDtcbiAgICB0aGlzLnRpbGVTaXplID0gc2l6ZTtcbn1cblxuVGlsZS5wcm90b3R5cGUgPSB7XG4gICAgLy8gdG9kbyB1bmhhcmRjb2RlXG4gICAgdGlsZUV4dGVudDogNDA5NixcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgaW50ZXJuYWwgcG9zTWF0cml4IHRoYXQgdGhpcyB0aWxlIHVzZXMgdG8gZGlzcGxheVxuICAgICAqIGl0c2VsZiBpbiBhIG1hcCwgZ2l2ZW4gYSBjb29yZGluYXRlIGFzICh6LCB4LCB5KSBhbmQgYSB0cmFuc2Zvcm1cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gelxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICovXG4gICAgY2FsY3VsYXRlTWF0cmljZXM6IGZ1bmN0aW9uKHosIHgsIHksIHRyYW5zZm9ybSkge1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgbW9kZWwtdmlldyBtYXRyaXggdGhhdCBjb252ZXJ0cyBmcm9tIHRoZSB0aWxlIGNvb3JkaW5hdGVzXG4gICAgICAgIC8vIHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAgICAgICAgdmFyIHRpbGVTY2FsZSA9IE1hdGgucG93KDIsIHopO1xuICAgICAgICB2YXIgc2NhbGUgPSB0cmFuc2Zvcm0ud29ybGRTaXplIC8gdGlsZVNjYWxlO1xuXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZVxuICAgICAgICB0aGlzLnNjYWxlID0gc2NhbGU7XG5cbiAgICAgICAgLy8gVGhlIHBvc2l0aW9uIG1hdHJpeFxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDY0QXJyYXkoMTYpO1xuICAgICAgICBtYXQ0LmlkZW50aXR5KHRoaXMucG9zTWF0cml4KTtcbiAgICAgICAgbWF0NC50cmFuc2xhdGUodGhpcy5wb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4LCBbeCAqIHNjYWxlLCB5ICogc2NhbGUsIDBdKTtcblxuICAgICAgICBtYXQ0LnNjYWxlKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgWyBzY2FsZSAvIHRoaXMudGlsZUV4dGVudCwgc2NhbGUgLyB0aGlzLnRpbGVFeHRlbnQsIDEgXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkodGhpcy5wb3NNYXRyaXgsIHRyYW5zZm9ybS5nZXRQcm9qTWF0cml4KCksIHRoaXMucG9zTWF0cml4KTtcblxuICAgICAgICAvLyBUaGUgZXh0cnVzaW9uIG1hdHJpeC5cbiAgICAgICAgdGhpcy5leE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIG1hdDQub3J0aG8odGhpcy5leE1hdHJpeCwgMCwgdHJhbnNmb3JtLndpZHRoLCB0cmFuc2Zvcm0uaGVpZ2h0LCAwLCAwLCAtMSk7XG4gICAgICAgIC8vbWF0NC5yb3RhdGVaKHRoaXMuZXhNYXRyaXgsIHRoaXMuZXhNYXRyaXgsIC10cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgICAgIC8vIDJ4MiBtYXRyaXggZm9yIHJvdGF0aW5nIHBvaW50c1xuICAgICAgICB0aGlzLnJvdGF0aW9uTWF0cml4ID0gbWF0Mi5jcmVhdGUoKTtcbiAgICAgICAgbWF0Mi5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCwgdGhpcy5yb3RhdGlvbk1hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcblxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5wb3NNYXRyaXgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGNvb3JkaW5hdGUgcG9zaXRpb24sIHpvb20gdGhhdCBjb29yZGluYXRlIHRvIG15IHpvb20gYW5kXG4gICAgICogc2NhbGUgYW5kIHJldHVybiBhIHBvc2l0aW9uIGluIHgsIHksIHNjYWxlXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHBvc2l0aW9uXG4gICAgICovXG4gICAgcG9zaXRpb25BdDogZnVuY3Rpb24oY29vcmQsIHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgY29vcmQgPSBjb29yZC56b29tVG8oTWF0aC5taW4odGhpcy5jb29yZC56LCBzb3VyY2VNYXhab29tKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiAoY29vcmQuY29sdW1uIC0gdGhpcy5jb29yZC54KSAqIDQwOTYsXG4gICAgICAgICAgICB5OiAoY29vcmQucm93IC0gdGhpcy5jb29yZC55KSAqIDQwOTYsXG4gICAgICAgICAgICBzY2FsZTogdGhpcy5zY2FsZVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGRhdGEgb2JqZWN0IHdpdGggYSAnYnVmZmVycycgcHJvcGVydHksIGxvYWQgaXQgaW50b1xuICAgICAqIHRoaXMgdGlsZSdzIGVsZW1lbnRHcm91cHMgYW5kIGJ1ZmZlcnMgcHJvcGVydGllcyBhbmQgc2V0IGxvYWRlZFxuICAgICAqIHRvIHRydWUuIElmIHRoZSBkYXRhIGlzIG51bGwsIGxpa2UgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHlcbiAgICAgKiBHZW9KU09OIHRpbGUsIG5vLW9wIGJ1dCBzdGlsbCBzZXQgbG9hZGVkIHRvIHRydWUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBlbXB0eSBHZW9KU09OIHRpbGVcbiAgICAgICAgaWYgKCFkYXRhKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXJzID0gbmV3IEJ1ZmZlclNldChkYXRhLmJ1ZmZlcnMpO1xuICAgICAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBkYXRhLmVsZW1lbnRHcm91cHM7XG4gICAgICAgIHRoaXMudGlsZUV4dGVudCA9IGRhdGEuZXh0ZW50O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBnaXZlbiBhIGRhdGEgb2JqZWN0IGFuZCBhIEdMIHBhaW50ZXIsIGRlc3Ryb3kgYW5kIHJlLWNyZWF0ZVxuICAgICAqIGFsbCBvZiBpdHMgYnVmZmVycy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyXG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICByZWxvYWRTeW1ib2xEYXRhOiBmdW5jdGlvbihkYXRhLCBwYWludGVyKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIC8vIHRoZSB0aWxlIGhhcyBiZWVuIGRlc3Ryb3llZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5nbHlwaEVsZW1lbnQuZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25WZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcblxuICAgICAgICB2YXIgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoZGF0YS5idWZmZXJzKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4ID0gYnVmZmVycy5nbHlwaFZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoRWxlbWVudCA9IGJ1ZmZlcnMuZ2x5cGhFbGVtZW50O1xuICAgICAgICB0aGlzLmJ1ZmZlcnMuaWNvblZlcnRleCA9IGJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50ID0gYnVmZmVycy5pY29uRWxlbWVudDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmNvbGxpc2lvbkJveFZlcnRleCA9IGJ1ZmZlcnMuY29sbGlzaW9uQm94VmVydGV4O1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzW2lkXSA9IGRhdGEuZWxlbWVudEdyb3Vwc1tpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWFrZSBzdXJlIHRoYXQgdGhpcyB0aWxlIGRvZXNuJ3Qgb3duIGFueSBkYXRhIHdpdGhpbiBhIGdpdmVuXG4gICAgICogcGFpbnRlciwgc28gdGhhdCBpdCBkb2Vzbid0IGNvbnN1bWUgYW55IG1lbW9yeSBvciBtYWludGFpblxuICAgICAqIGFueSByZWZlcmVuY2VzIHRvIHRoZSBwYWludGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyIGdsIHBhaW50ZXIgb2JqZWN0XG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB1bmxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihwYWludGVyKSB7XG4gICAgICAgIGZvciAodmFyIGIgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlcnNbYl0uZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSBudWxsO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZUNvb3JkO1xuXG5mdW5jdGlvbiBUaWxlQ29vcmQoeiwgeCwgeSwgdykge1xuICAgIGlmICh3ID09PSB1bmRlZmluZWQpIHcgPSAwO1xuICAgIHRoaXMueiA9IHo7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMudyA9IHc7XG5cbiAgICAvLyBjYWxjdWxhdGUgaWRcbiAgICB3ICo9IDI7XG4gICAgaWYgKHcgPCAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB2YXIgZGltID0gMSA8PCB0aGlzLno7XG4gICAgdGhpcy5pZCA9ICgoZGltICogZGltICogdyArIGRpbSAqIHRoaXMueSArIHRoaXMueCkgKiAzMikgKyB0aGlzLno7XG59XG5cblRpbGVDb29yZC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy56ICsgXCIvXCIgKyB0aGlzLnggKyBcIi9cIiArIHRoaXMueTtcbn07XG5cbi8vIFBhcnNlIGEgcGFja2VkIGludGVnZXIgaWQgaW50byBhIFRpbGVDb29yZCBvYmplY3RcblRpbGVDb29yZC5mcm9tSUQgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciB6ID0gaWQgJSAzMiwgZGltID0gMSA8PCB6O1xuICAgIHZhciB4eSA9ICgoaWQgLSB6KSAvIDMyKTtcbiAgICB2YXIgeCA9IHh5ICUgZGltLCB5ID0gKCh4eSAtIHgpIC8gZGltKSAlIGRpbTtcbiAgICB2YXIgdyA9IE1hdGguZmxvb3IoeHkgLyAoZGltICogZGltKSk7XG4gICAgaWYgKHcgJSAyICE9PSAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB3IC89IDI7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQoeiwgeCwgeSwgdyk7XG59O1xuXG4vLyBnaXZlbiBhIGxpc3Qgb2YgdXJscywgY2hvb3NlIGEgdXJsIHRlbXBsYXRlIGFuZCByZXR1cm4gYSB0aWxlIFVSTFxuVGlsZUNvb3JkLnByb3RvdHlwZS51cmwgPSBmdW5jdGlvbih1cmxzLCBzb3VyY2VNYXhab29tKSB7XG4gICAgcmV0dXJuIHVybHNbKHRoaXMueCArIHRoaXMueSkgJSB1cmxzLmxlbmd0aF1cbiAgICAgICAgLnJlcGxhY2UoJ3twcmVmaXh9JywgKHRoaXMueCAlIDE2KS50b1N0cmluZygxNikgKyAodGhpcy55ICUgMTYpLnRvU3RyaW5nKDE2KSlcbiAgICAgICAgLnJlcGxhY2UoJ3t6fScsIE1hdGgubWluKHRoaXMueiwgc291cmNlTWF4Wm9vbSB8fCB0aGlzLnopKVxuICAgICAgICAucmVwbGFjZSgne3h9JywgdGhpcy54KVxuICAgICAgICAucmVwbGFjZSgne3l9JywgdGhpcy55KTtcbn07XG5cbi8vIFJldHVybiB0aGUgY29vcmRpbmF0ZSBvZiB0aGUgcGFyZW50IHRpbGVcblRpbGVDb29yZC5wcm90b3R5cGUucGFyZW50ID0gZnVuY3Rpb24oc291cmNlTWF4Wm9vbSkge1xuICAgIGlmICh0aGlzLnogPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgLy8gdGhlIGlkIHJlcHJlc2VudHMgYW4gb3ZlcnNjYWxlZCB0aWxlLCByZXR1cm4gdGhlIHNhbWUgY29vcmRpbmF0ZXMgd2l0aCBhIGxvd2VyIHpcbiAgICBpZiAodGhpcy56ID4gc291cmNlTWF4Wm9vbSkge1xuICAgICAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCBNYXRoLmZsb29yKHRoaXMueCAvIDIpLCBNYXRoLmZsb29yKHRoaXMueSAvIDIpLCB0aGlzLncpO1xufTtcblxuVGlsZUNvb3JkLnByb3RvdHlwZS53cmFwcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQodGhpcy56LCB0aGlzLngsIHRoaXMueSwgMCk7XG59O1xuXG4vLyBSZXR1cm4gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB0aWxlJ3MgY2hpbGRyZW5cblRpbGVDb29yZC5wcm90b3R5cGUuY2hpbGRyZW4gPSBmdW5jdGlvbihzb3VyY2VNYXhab29tKSB7XG5cbiAgICBpZiAodGhpcy56ID49IHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgLy8gcmV0dXJuIGEgc2luZ2xlIHRpbGUgY29vcmQgcmVwcmVzZW50aW5nIGEgYW4gb3ZlcnNjYWxlZCB0aWxlXG4gICAgICAgIHJldHVybiBbbmV3IFRpbGVDb29yZCh0aGlzLnogKyAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KV07XG4gICAgfVxuXG4gICAgdmFyIHogPSB0aGlzLnogKyAxO1xuICAgIHZhciB4ID0gdGhpcy54ICogMjtcbiAgICB2YXIgeSA9IHRoaXMueSAqIDI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IFRpbGVDb29yZCh6LCB4LCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHgsIHkgKyAxLCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5ICsgMSwgdGhpcy53KVxuICAgIF07XG59O1xuXG4vLyBUYWtlbiBmcm9tIHBvbHltYXBzIHNyYy9MYXllci5qc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3NpbXBsZWdlby9wb2x5bWFwcy9ibG9iL21hc3Rlci9zcmMvTGF5ZXIuanMjTDMzMy1MMzgzXG5cbmZ1bmN0aW9uIGVkZ2UoYSwgYikge1xuICAgIGlmIChhLnJvdyA+IGIucm93KSB7IHZhciB0ID0gYTsgYSA9IGI7IGIgPSB0OyB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDA6IGEuY29sdW1uLFxuICAgICAgICB5MDogYS5yb3csXG4gICAgICAgIHgxOiBiLmNvbHVtbixcbiAgICAgICAgeTE6IGIucm93LFxuICAgICAgICBkeDogYi5jb2x1bW4gLSBhLmNvbHVtbixcbiAgICAgICAgZHk6IGIucm93IC0gYS5yb3dcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBzY2FuU3BhbnMoZTAsIGUxLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciB5MCA9IE1hdGgubWF4KHltaW4sIE1hdGguZmxvb3IoZTEueTApKTtcbiAgICB2YXIgeTEgPSBNYXRoLm1pbih5bWF4LCBNYXRoLmNlaWwoZTEueTEpKTtcblxuICAgIC8vIHNvcnQgZWRnZXMgYnkgeC1jb29yZGluYXRlXG4gICAgaWYgKChlMC54MCA9PT0gZTEueDAgJiYgZTAueTAgPT09IGUxLnkwKSA/XG4gICAgICAgICAgICAoZTAueDAgKyBlMS5keSAvIGUwLmR5ICogZTAuZHggPCBlMS54MSkgOlxuICAgICAgICAgICAgKGUwLngxIC0gZTEuZHkgLyBlMC5keSAqIGUwLmR4IDwgZTEueDApKSB7XG4gICAgICAgIHZhciB0ID0gZTA7IGUwID0gZTE7IGUxID0gdDtcbiAgICB9XG5cbiAgICAvLyBzY2FuIGxpbmVzIVxuICAgIHZhciBtMCA9IGUwLmR4IC8gZTAuZHk7XG4gICAgdmFyIG0xID0gZTEuZHggLyBlMS5keTtcbiAgICB2YXIgZDAgPSBlMC5keCA+IDA7IC8vIHVzZSB5ICsgMSB0byBjb21wdXRlIHgwXG4gICAgdmFyIGQxID0gZTEuZHggPCAwOyAvLyB1c2UgeSArIDEgdG8gY29tcHV0ZSB4MVxuICAgIGZvciAodmFyIHkgPSB5MDsgeSA8IHkxOyB5KyspIHtcbiAgICAgICAgdmFyIHgwID0gbTAgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMC5keSwgeSArIGQwIC0gZTAueTApKSArIGUwLngwO1xuICAgICAgICB2YXIgeDEgPSBtMSAqIE1hdGgubWF4KDAsIE1hdGgubWluKGUxLmR5LCB5ICsgZDEgLSBlMS55MCkpICsgZTEueDA7XG4gICAgICAgIHNjYW5MaW5lKE1hdGguZmxvb3IoeDEpLCBNYXRoLmNlaWwoeDApLCB5KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNjYW5UcmlhbmdsZShhLCBiLCBjLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciBhYiA9IGVkZ2UoYSwgYiksXG4gICAgICAgIGJjID0gZWRnZShiLCBjKSxcbiAgICAgICAgY2EgPSBlZGdlKGMsIGEpO1xuXG4gICAgdmFyIHQ7XG5cbiAgICAvLyBzb3J0IGVkZ2VzIGJ5IHktbGVuZ3RoXG4gICAgaWYgKGFiLmR5ID4gYmMuZHkpIHsgdCA9IGFiOyBhYiA9IGJjOyBiYyA9IHQ7IH1cbiAgICBpZiAoYWIuZHkgPiBjYS5keSkgeyB0ID0gYWI7IGFiID0gY2E7IGNhID0gdDsgfVxuICAgIGlmIChiYy5keSA+IGNhLmR5KSB7IHQgPSBiYzsgYmMgPSBjYTsgY2EgPSB0OyB9XG5cbiAgICAvLyBzY2FuIHNwYW4hIHNjYW4gc3BhbiFcbiAgICBpZiAoYWIuZHkpIHNjYW5TcGFucyhjYSwgYWIsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbiAgICBpZiAoYmMuZHkpIHNjYW5TcGFucyhjYSwgYmMsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbn1cblxuVGlsZUNvb3JkLmNvdmVyID0gZnVuY3Rpb24oeiwgYm91bmRzLCBhY3R1YWxaKSB7XG4gICAgdmFyIHRpbGVzID0gMSA8PCB6O1xuICAgIHZhciB0ID0ge307XG5cbiAgICBmdW5jdGlvbiBzY2FuTGluZSh4MCwgeDEsIHkpIHtcbiAgICAgICAgdmFyIHgsIHd4O1xuICAgICAgICBpZiAoeSA+PSAwICYmIHkgPD0gdGlsZXMpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IHgwOyB4IDwgeDE7IHgrKykge1xuICAgICAgICAgICAgICAgIHd4ID0gKHggKyB0aWxlcykgJSB0aWxlcztcbiAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBuZXcgVGlsZUNvb3JkKGFjdHVhbFosIHd4LCB5LCBNYXRoLmZsb29yKHggLyB0aWxlcykpO1xuICAgICAgICAgICAgICAgIHRbY29vcmQuaWRdID0gY29vcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXZpZGUgdGhlIHNjcmVlbiB1cCBpbiB0d28gdHJpYW5nbGVzIGFuZCBzY2FuIGVhY2ggb2YgdGhlbTpcbiAgICAvLyArLS0tL1xuICAgIC8vIHwgLyB8XG4gICAgLy8gLy0tLStcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzBdLCBib3VuZHNbMV0sIGJvdW5kc1syXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzJdLCBib3VuZHNbM10sIGJvdW5kc1swXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0KS5tYXAoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRbaWRdO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQ2FjaGUgPSByZXF1aXJlKCcuLi91dGlsL21ydV9jYWNoZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUaWxlUHlyYW1pZDtcblxuLyoqXG4gKiBBIHRpbGUgcHlyYW1pZCBpcyBhIHNwZWNpYWxpemVkIGNhY2hlIGFuZCBkYXRhc3RydWN0dXJlXG4gKiB0aGF0IGNvbnRhaW5zIHRpbGVzLiBJdCdzIHVzZWQgYnkgc291cmNlcyB0byBtYW5hZ2UgdGhlaXJcbiAqIGRhdGEuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnRpbGVTaXplXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5taW56b29tXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5tYXh6b29tXG4gKi9cbmZ1bmN0aW9uIFRpbGVQeXJhbWlkKG9wdGlvbnMpIHtcbiAgICB0aGlzLnRpbGVTaXplID0gb3B0aW9ucy50aWxlU2l6ZTtcbiAgICB0aGlzLm1pbnpvb20gPSBvcHRpb25zLm1pbnpvb207XG4gICAgdGhpcy5tYXh6b29tID0gb3B0aW9ucy5tYXh6b29tO1xuICAgIHRoaXMucmVwYXJzZU92ZXJzY2FsZWQgPSBvcHRpb25zLnJlcGFyc2VPdmVyc2NhbGVkO1xuXG4gICAgdGhpcy5fbG9hZCA9IG9wdGlvbnMubG9hZDtcbiAgICB0aGlzLl9hYm9ydCA9IG9wdGlvbnMuYWJvcnQ7XG4gICAgdGhpcy5fdW5sb2FkID0gb3B0aW9ucy51bmxvYWQ7XG4gICAgdGhpcy5fYWRkID0gb3B0aW9ucy5hZGQ7XG4gICAgdGhpcy5fcmVtb3ZlID0gb3B0aW9ucy5yZW1vdmU7XG4gICAgdGhpcy5fcmVkb1BsYWNlbWVudCA9IG9wdGlvbnMucmVkb1BsYWNlbWVudDtcblxuICAgIHRoaXMuX3RpbGVzID0ge307XG4gICAgdGhpcy5fY2FjaGUgPSBuZXcgQ2FjaGUob3B0aW9ucy5jYWNoZVNpemUsIGZ1bmN0aW9uKHRpbGUpIHsgcmV0dXJuIHRoaXMuX3VubG9hZCh0aWxlKTsgfS5iaW5kKHRoaXMpKTtcbn1cblxuVGlsZVB5cmFtaWQucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIENvbmZpcm0gdGhhdCBldmVyeSB0cmFja2VkIHRpbGUgaXMgbG9hZGVkLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIGFsbCB0aWxlcyBhcmUgbG9hZGVkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgdCBpbiB0aGlzLl90aWxlcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl90aWxlc1t0XS5sb2FkZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRpbGUgaWRzIG9yZGVyZWQgd2l0aCB6LW9yZGVyLCBhbmQgY2FzdCB0byBudW1iZXJzXG4gICAgICogQHJldHVybnMge0FycmF5PG51bWJlcj59IGlkc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgb3JkZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl90aWxlcylcbiAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIChiICUgMzIpIC0gKGEgJSAzMik7IH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGlkKSB7IHJldHVybiAraWQ7IH0pO1xuICAgIH0sXG5cbiAgICByZW5kZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yZGVyZWRJRHMoKS5maWx0ZXIoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90aWxlc1tpZF0ubG9hZGVkICYmICF0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICByZWxvYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9jYWNoZS5yZXNldCgpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMuX3RpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2FkKHRoaXMuX3RpbGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzcGVjaWZpYyB0aWxlIGJ5IGlkXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCB0aWxlIGlkXG4gICAgICogQHJldHVybnMge09iamVjdH0gdGlsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0VGlsZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RpbGVzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogZ2V0IHRoZSB6b29tIGxldmVsIGFkanVzdGVkIGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtYXAgYW5kIHNvdXJjZSB0aWxlc2l6ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICogQHJldHVybnMge251bWJlcn0gem9vbSBsZXZlbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm0uem9vbSArIE1hdGgubG9nKHRyYW5zZm9ybS50aWxlU2l6ZSAvIHRoaXMudGlsZVNpemUpIC8gTWF0aC5MTjI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHpvb20gbGV2ZWwgdGhhdCB3aWxsIGNvdmVyIGFsbCB0aWxlcyBpbiBhIGdpdmVuIHRyYW5zZm9ybVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSB6b29tIGxldmVsXG4gICAgICovXG4gICAgY292ZXJpbmdab29tTGV2ZWw6IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldFpvb20odHJhbnNmb3JtKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgdHJhbnNmb3JtLCByZXR1cm4gYWxsIGNvb3JkaW5hdGVzIHRoYXQgY291bGQgY292ZXIgdGhhdFxuICAgICAqIHRyYW5zZm9ybSBmb3IgYSBjb3ZlcmluZyB6b29tIGxldmVsLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8VGlsZT59IHRpbGVzXG4gICAgICovXG4gICAgY292ZXJpbmdUaWxlczogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHZhciB6ID0gdGhpcy5jb3ZlcmluZ1pvb21MZXZlbCh0cmFuc2Zvcm0pO1xuICAgICAgICB2YXIgYWN0dWFsWiA9IHo7XG5cbiAgICAgICAgaWYgKHogPCB0aGlzLm1pbnpvb20pIHJldHVybiBbXTtcbiAgICAgICAgaWYgKHogPiB0aGlzLm1heHpvb20pIHogPSB0aGlzLm1heHpvb207XG5cbiAgICAgICAgdmFyIHRyID0gdHJhbnNmb3JtLFxuICAgICAgICAgICAgdGlsZUNlbnRlciA9IHRyLmxvY2F0aW9uQ29vcmRpbmF0ZSh0ci5jZW50ZXIpLl96b29tVG8oeiksXG4gICAgICAgICAgICBjZW50ZXJQb2ludCA9IG5ldyBQb2ludCh0aWxlQ2VudGVyLmNvbHVtbiAtIDAuNSwgdGlsZUNlbnRlci5yb3cgLSAwLjUpO1xuXG4gICAgICAgIHJldHVybiBUaWxlQ29vcmQuY292ZXIoeiwgW1xuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCgwLCAwKSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQodHIud2lkdGgsIDApKS5fem9vbVRvKHopLFxuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCh0ci53aWR0aCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQoMCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KVxuICAgICAgICBdLCB0aGlzLnJlcGFyc2VPdmVyc2NhbGVkID8gYWN0dWFsWiA6IHopLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGNlbnRlclBvaW50LmRpc3QoYSkgLSBjZW50ZXJQb2ludC5kaXN0KGIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmluZCBjaGlsZHJlbiBvZiB0aGUgZ2l2ZW4gdGlsZSAodXAgdG8gbWF4Q292ZXJpbmdab29tKSB0aGF0IGFyZSBhbHJlYWR5IGxvYWRlZDtcbiAgICAgKiBhZGRzIGZvdW5kIHRpbGVzIHRvIHJldGFpbiBvYmplY3Q7IHJldHVybnMgdHJ1ZSBpZiBjaGlsZHJlbiBjb21wbGV0ZWx5IGNvdmVyIHRoZSB0aWxlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENvdmVyaW5nWm9vbVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0YWluXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIG9wZXJhdGlvbiB3YXMgY29tcGxldGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRDaGlsZHJlbjogZnVuY3Rpb24oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IHRydWU7XG4gICAgICAgIHZhciB6ID0gY29vcmQuejtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGNvb3JkLmNoaWxkcmVuKHRoaXMubWF4em9vbSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBjb29yZHNbaV0uaWQ7XG4gICAgICAgICAgICBpZiAodGhpcy5fdGlsZXNbaWRdICYmIHRoaXMuX3RpbGVzW2lkXS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICByZXRhaW5baWRdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29tcGxldGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoeiA8IG1heENvdmVyaW5nWm9vbSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBHbyBmdXJ0aGVyIGRvd24gdGhlIGhpZXJhcmNoeSB0byBmaW5kIG1vcmUgdW5sb2FkZWQgY2hpbGRyZW4uXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3Jkc1tpXSwgbWF4Q292ZXJpbmdab29tLCByZXRhaW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcGxldGU7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBsb2FkZWQgcGFyZW50IG9mIHRoZSBnaXZlbiB0aWxlICh1cCB0byBtaW5Db3ZlcmluZ1pvb20pO1xuICAgICAqIGFkZHMgdGhlIGZvdW5kIHRpbGUgdG8gcmV0YWluIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgdGlsZSBpZiBmb3VuZFxuICAgICAqXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5Db3ZlcmluZ1pvb21cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJldGFpblxuICAgICAqIEByZXR1cm5zIHtUaWxlfSB0aWxlIG9iamVjdFxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRQYXJlbnQ6IGZ1bmN0aW9uKGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbikge1xuICAgICAgICBmb3IgKHZhciB6ID0gY29vcmQueiAtIDE7IHogPj0gbWluQ292ZXJpbmdab29tOyB6LS0pIHtcbiAgICAgICAgICAgIGNvb3JkID0gY29vcmQucGFyZW50KHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2Nvb3JkLmlkXTtcbiAgICAgICAgICAgIGlmICh0aWxlICYmIHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0YWluW2Nvb3JkLmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aWxlcyB0aGF0IGFyZSBvdXRzaWRlIHRoZSB2aWV3cG9ydCBhbmQgYWRkcyBuZXcgdGlsZXMgdGhhdFxuICAgICAqIGFyZSBpbnNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXNlZCwgdHJhbnNmb3JtLCBmYWRlRHVyYXRpb24pIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBjb29yZDtcbiAgICAgICAgdmFyIHRpbGU7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBvdmVyem9vbWluZy91bmRlcnpvb21pbmcgYW1vdW50cy5cbiAgICAgICAgdmFyIHpvb20gPSBNYXRoLmZsb29yKHRoaXMuZ2V0Wm9vbSh0cmFuc2Zvcm0pKTtcbiAgICAgICAgdmFyIG1pbkNvdmVyaW5nWm9vbSA9IHV0aWwuY2xhbXAoem9vbSAtIDEwLCB0aGlzLm1pbnpvb20sIHRoaXMubWF4em9vbSk7XG4gICAgICAgIHZhciBtYXhDb3ZlcmluZ1pvb20gPSB1dGlsLmNsYW1wKHpvb20gKyAxLCAgdGhpcy5taW56b29tLCB0aGlzLm1heHpvb20pO1xuXG4gICAgICAgIC8vIFJldGFpbiBpcyBhIGxpc3Qgb2YgdGlsZXMgdGhhdCB3ZSBzaG91bGRuJ3QgZGVsZXRlLCBldmVuIGlmIHRoZXkgYXJlIG5vdFxuICAgICAgICAvLyB0aGUgbW9zdCBpZGVhbCB0aWxlIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydC4gVGhpcyBtYXkgaW5jbHVkZSB0aWxlcyBsaWtlXG4gICAgICAgIC8vIHBhcmVudCBvciBjaGlsZCB0aWxlcyB0aGF0IGFyZSAqYWxyZWFkeSogbG9hZGVkLlxuICAgICAgICB2YXIgcmV0YWluID0ge307XG4gICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICAvLyBDb3ZlcmVkIGlzIGEgbGlzdCBvZiByZXRhaW5lZCB0aWxlcyB3aG8ncyBhcmVhcyBhcmUgZnVsbCBjb3ZlcmVkIGJ5IG90aGVyLFxuICAgICAgICAvLyBiZXR0ZXIsIHJldGFpbmVkIHRpbGVzLiBUaGV5IGFyZSBub3QgZHJhd24gc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fY292ZXJlZFRpbGVzID0ge307XG5cbiAgICAgICAgdmFyIHJlcXVpcmVkID0gdXNlZCA/IHRoaXMuY292ZXJpbmdUaWxlcyh0cmFuc2Zvcm0pIDogW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXF1aXJlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29vcmQgPSByZXF1aXJlZFtpXTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmFkZFRpbGUoY29vcmQpO1xuXG4gICAgICAgICAgICByZXRhaW5bY29vcmQuaWRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHRpbGUubG9hZGVkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBUaGUgdGlsZSB3ZSByZXF1aXJlIGlzIG5vdCB5ZXQgbG9hZGVkLlxuICAgICAgICAgICAgLy8gUmV0YWluIGNoaWxkIG9yIHBhcmVudCB0aWxlcyB0aGF0IGNvdmVyIHRoZSBzYW1lIGFyZWEuXG4gICAgICAgICAgICBpZiAoIXRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3JkLCBtYXhDb3ZlcmluZ1pvb20sIHJldGFpbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmRMb2FkZWRQYXJlbnQoY29vcmQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHJldGFpbikge1xuICAgICAgICAgICAgY29vcmQgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1tpZF07XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aWxlLnRpbWVBZGRlZCA+IG5vdyAtIChmYWRlRHVyYXRpb24gfHwgMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHRpbGUgaXMgc3RpbGwgZmFkaW5nIGluLiBGaW5kIHRpbGVzIHRvIGNyb3NzLWZhZGUgd2l0aCBpdC5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maW5kTG9hZGVkQ2hpbGRyZW4oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0YWluW2lkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5kTG9hZGVkUGFyZW50KGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0aWxlcyB3ZSBkb24ndCBuZWVkIGFueW1vcmUuXG4gICAgICAgIHZhciByZW1vdmUgPSB1dGlsLmtleXNEaWZmZXJlbmNlKHRoaXMuX3RpbGVzLCByZXRhaW4pO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVRpbGUoK3JlbW92ZVtpXSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgdGlsZSwgZ2l2ZW4gaXRzIGNvb3JkaW5hdGUsIHRvIHRoZSBweXJhbWlkLlxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7Q29vcmRpbmF0ZX0gdGhlIGNvb3JkaW5hdGUuXG4gICAgICovXG4gICAgYWRkVGlsZTogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl90aWxlc1tjb29yZC5pZF07XG4gICAgICAgIGlmICh0aWxlKVxuICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG5cbiAgICAgICAgdmFyIHdyYXBwZWQgPSBjb29yZC53cmFwcGVkKCk7XG4gICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1t3cmFwcGVkLmlkXTtcblxuICAgICAgICBpZiAoIXRpbGUpIHtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl9jYWNoZS5nZXQod3JhcHBlZC5pZCk7XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aGlzLl9yZWRvUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVkb1BsYWNlbWVudCh0aWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGlsZSkge1xuICAgICAgICAgICAgdmFyIHpvb20gPSBjb29yZC56O1xuICAgICAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gem9vbSA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLm1heHpvb20pIDogMTtcbiAgICAgICAgICAgIHRpbGUgPSBuZXcgVGlsZSh3cmFwcGVkLCB0aGlzLnRpbGVTaXplICogb3ZlcnNjYWxpbmcpO1xuICAgICAgICAgICAgdGhpcy5fbG9hZCh0aWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbGUudXNlcysrO1xuICAgICAgICB0aGlzLl90aWxlc1tjb29yZC5pZF0gPSB0aWxlO1xuICAgICAgICB0aGlzLl9hZGQodGlsZSwgY29vcmQpO1xuXG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSB0aWxlLCBnaXZlbiBpdHMgaWQsIGZyb20gdGhlIHB5cmFtaWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIHRpbGUgaWRcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBub3RoaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICByZW1vdmVUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2lkXTtcbiAgICAgICAgaWYgKCF0aWxlKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRpbGUudXNlcy0tO1xuICAgICAgICBkZWxldGUgdGhpcy5fdGlsZXNbaWRdO1xuICAgICAgICB0aGlzLl9yZW1vdmUodGlsZSk7XG5cbiAgICAgICAgaWYgKHRpbGUudXNlcyA+IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZS5hZGQodGlsZS5jb29yZC53cmFwcGVkKCkuaWQsIHRpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fYWJvcnQodGlsZSk7XG4gICAgICAgICAgICB0aGlzLl91bmxvYWQodGlsZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCB0aWxlcyBmcm9tIHRoaXMgcHlyYW1pZFxuICAgICAqL1xuICAgIGNsZWFyVGlsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBpZCBpbiB0aGlzLl90aWxlcylcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlVGlsZShpZCk7XG4gICAgICAgIHRoaXMuX2NhY2hlLnJlc2V0KCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZvciBhIGdpdmVuIGNvb3JkaW5hdGUsIHNlYXJjaCB0aHJvdWdoIG91ciBjdXJyZW50IHRpbGVzIGFuZCBhdHRlbXB0XG4gICAgICogdG8gZmluZCBhIHRpbGUgYXQgdGhhdCBwb2ludFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSB0aWxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aWxlQXQ6IGZ1bmN0aW9uKGNvb3JkKSB7XG4gICAgICAgIHZhciBpZHMgPSB0aGlzLm9yZGVyZWRJRHMoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gdGhpcy5fdGlsZXNbaWRzW2ldXTtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aWxlLnBvc2l0aW9uQXQoY29vcmQsIHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICBpZiAocG9zICYmIHBvcy54ID49IDAgJiYgcG9zLnggPCA0MDk2ICYmIHBvcy55ID49IDAgJiYgcG9zLnkgPCA0MDk2KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGNsaWNrIGlzIHdpdGhpbiB0aGUgdmlld3BvcnQuIFRoZXJlIGlzIG9ubHkgZXZlciBvbmUgdGlsZSBpblxuICAgICAgICAgICAgICAgIC8vIGEgbGF5ZXIgdGhhdCBoYXMgdGhpcyBwcm9wZXJ0eS5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB0aWxlOiB0aWxlLFxuICAgICAgICAgICAgICAgICAgICB4OiBwb3MueCxcbiAgICAgICAgICAgICAgICAgICAgeTogcG9zLnksXG4gICAgICAgICAgICAgICAgICAgIHNjYWxlOiBwb3Muc2NhbGVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlU291cmNlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlU291cmNlKG9wdGlvbnMpIHtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLCB1dGlsLnBpY2sob3B0aW9ucywgWyd1cmwnLCAndGlsZVNpemUnXSkpO1xuXG4gICAgaWYgKHRoaXMudGlsZVNpemUgIT09IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyJyk7XG4gICAgfVxuXG4gICAgU291cmNlLl9sb2FkVGlsZUpTT04uY2FsbCh0aGlzLCBvcHRpb25zKTtcbn1cblxuVmVjdG9yVGlsZVNvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIG1pbnpvb206IDAsXG4gICAgbWF4em9vbTogMjIsXG4gICAgdGlsZVNpemU6IDUxMixcbiAgICByZXBhcnNlT3ZlcnNjYWxlZDogdHJ1ZSxcbiAgICBfbG9hZGVkOiBmYWxzZSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9weXJhbWlkICYmIHRoaXMuX3B5cmFtaWQubG9hZGVkKCk7XG4gICAgfSxcblxuICAgIHVwZGF0ZTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIGlmICh0aGlzLl9weXJhbWlkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVkb1BsYWNlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fcHlyYW1pZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQub3JkZXJlZElEcygpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl9weXJhbWlkLmdldFRpbGUoaWRzW2ldKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcbiAgICBmZWF0dXJlc0F0OiBTb3VyY2UuX3ZlY3RvckZlYXR1cmVzQXQsXG5cbiAgICBfbG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gdGlsZS5jb29yZC56ID4gdGhpcy5tYXh6b29tID8gTWF0aC5wb3coMiwgdGlsZS5jb29yZC56IC0gdGhpcy5tYXh6b29tKSA6IDE7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICB1cmw6IHRpbGUuY29vcmQudXJsKHRoaXMudGlsZXMsIHRoaXMubWF4em9vbSksXG4gICAgICAgICAgICB1aWQ6IHRpbGUudWlkLFxuICAgICAgICAgICAgY29vcmQ6IHRpbGUuY29vcmQsXG4gICAgICAgICAgICB6b29tOiB0aWxlLmNvb3JkLnosXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb20sXG4gICAgICAgICAgICB0aWxlU2l6ZTogdGhpcy50aWxlU2l6ZSAqIG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgc291cmNlOiB0aGlzLmlkLFxuICAgICAgICAgICAgb3ZlcnNjYWxpbmc6IG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgYW5nbGU6IHRoaXMubWFwLnRyYW5zZm9ybS5hbmdsZSxcbiAgICAgICAgICAgIHBpdGNoOiB0aGlzLm1hcC50cmFuc2Zvcm0ucGl0Y2gsXG4gICAgICAgICAgICBjb2xsaXNpb25EZWJ1ZzogdGhpcy5tYXAuY29sbGlzaW9uRGVidWdcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGlsZS53b3JrZXJJRCkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbG9hZCB0aWxlJywgcGFyYW1zLCB0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcywgdGlsZSksIHRpbGUud29ya2VySUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIHRpbGUnLCBwYXJhbXMsIHRoaXMuX3RpbGVMb2FkZWQuYmluZCh0aGlzLCB0aWxlKSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX3RpbGVMb2FkZWQ6IGZ1bmN0aW9uKHRpbGUsIGVyciwgZGF0YSkge1xuICAgICAgICBpZiAodGlsZS5hYm9ydGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5lcnJvcicsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLmxvYWRWZWN0b3JEYXRhKGRhdGEpO1xuXG4gICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgdGlsZS5yZWRvV2hlbkRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdhYm9ydCB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9yZWRvVGlsZVBsYWNlbWVudDogZnVuY3Rpb24odGlsZSkge1xuXG4gICAgICAgIGlmICghdGlsZS5sb2FkZWQgfHwgdGlsZS5yZWRvaW5nUGxhY2VtZW50KSB7XG4gICAgICAgICAgICB0aWxlLnJlZG9XaGVuRG9uZSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdyZWRvIHBsYWNlbWVudCcsIHtcbiAgICAgICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBhbmdsZTogdGhpcy5tYXAudHJhbnNmb3JtLmFuZ2xlLFxuICAgICAgICAgICAgcGl0Y2g6IHRoaXMubWFwLnRyYW5zZm9ybS5waXRjaCxcbiAgICAgICAgICAgIGNvbGxpc2lvbkRlYnVnOiB0aGlzLm1hcC5jb2xsaXNpb25EZWJ1Z1xuICAgICAgICB9LCBkb25lLmJpbmQodGhpcyksIHRpbGUud29ya2VySUQpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGRvbmUoXywgZGF0YSkge1xuICAgICAgICAgICAgdGlsZS5yZWxvYWRTeW1ib2xEYXRhKGRhdGEsIHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuXG4gICAgICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICAgICAgICAgIHRpbGUucmVkb1doZW5Eb25lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuLi9nZW8vY29vcmRpbmF0ZScpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWaWRlb1NvdXJjZTtcblxuLyoqXG4gKiBDcmVhdGUgYSBWaWRlbyBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICogQGNsYXNzIFZpZGVvU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge1N0cmluZ3xBcnJheX0gb3B0aW9ucy51cmwgQSBzdHJpbmcgb3IgYXJyYXkgb2YgVVJMKHMpIHRvIHZpZGVvIGZpbGVzXG4gKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLmNvb3JkaW5hdGVzIGxhdCxsbmcgY29vcmRpbmF0ZXMgaW4gb3JkZXIgY2xvY2t3aXNlIHN0YXJ0aW5nIGF0IHRoZSB0b3AgbGVmdDogdGwsIHRyLCBiciwgYmxcbiAqIEBleGFtcGxlXG4gKiB2YXIgc291cmNlT2JqID0gbmV3IG1hcGJveGdsLlZpZGVvU291cmNlKHtcbiAqICAgIHVybDogW1xuICogICAgICAgICdodHRwczovL3d3dy5tYXBib3guY29tL3ZpZGVvcy9iYWx0aW1vcmUtc21va2UubXA0JyxcbiAqICAgICAgICAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS92aWRlb3MvYmFsdGltb3JlLXNtb2tlLndlYm0nXG4gKiAgICBdLFxuICogICAgY29vcmRpbmF0ZXM6IFtcbiAqICAgICAgICBbMzkuMTg1Nzk5MDcyMjk3NDgsIC03Ni41NDMzNTczNzIyODM5NF0sXG4gKiAgICAgICAgWzM5LjE4MzgzNjQ4NDc1ODcsIC03Ni41MjgwMzY1OTQzOTA4N10sXG4gKiAgICAgICAgWzM5LjE3NjgzMzkyNTA3NjA2LCAtNzYuNTI5NTM4NjMxNDM5Ml0sXG4gKiAgICAgICAgWzM5LjE3ODc2MzQ0MTA2NjQyLCAtNzYuNTQ1MjAyNzMyMDg2MThdXG4gKiAgICBdXG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBWaWRlb1NvdXJjZShvcHRpb25zKSB7XG4gICAgdGhpcy5jb29yZGluYXRlcyA9IG9wdGlvbnMuY29vcmRpbmF0ZXM7XG5cbiAgICBhamF4LmdldFZpZGVvKG9wdGlvbnMudXJsLCBmdW5jdGlvbihlcnIsIHZpZGVvKSB7XG4gICAgICAgIC8vIEBUT0RPIGhhbmRsZSBlcnJvcnMgdmlhIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy52aWRlbyA9IHZpZGVvO1xuICAgICAgICB0aGlzLnZpZGVvLmxvb3AgPSB0cnVlO1xuXG4gICAgICAgIHZhciBsb29wSUQ7XG5cbiAgICAgICAgLy8gc3RhcnQgcmVwYWludGluZyB3aGVuIHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gICAgICAgIHRoaXMudmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheWluZycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbG9vcElEID0gdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoSW5maW5pdHkpO1xuICAgICAgICAgICAgdGhpcy5tYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gc3RvcCByZXBhaW50aW5nIHdoZW4gdmlkZW8gc3RvcHNcbiAgICAgICAgdGhpcy52aWRlby5hZGRFdmVudExpc3RlbmVyKCdwYXVzZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5jYW5jZWwobG9vcElEKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcCkge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJyk7XG4gICAgICAgIH1cbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgSFRNTCB2aWRlbyBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRWaWRlbzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvO1xuICAgIH0sXG5cbiAgICBvbkFkZDogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMubWFwID0gbWFwO1xuICAgICAgICBpZiAodGhpcy52aWRlbykge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogQ2FsY3VsYXRlIHdoaWNoIG1lcmNhdG9yIHRpbGUgaXMgc3VpdGFibGUgZm9yIHJlbmRlcmluZyB0aGUgdmlkZW8gaW5cbiAgICAgICAgICogYW5kIGNyZWF0ZSBhIGJ1ZmZlciB3aXRoIHRoZSBjb3JuZXIgY29vcmRpbmF0ZXMuIFRoZXNlIGNvb3JkaW5hdGVzXG4gICAgICAgICAqIG1heSBiZSBvdXRzaWRlIHRoZSB0aWxlLCBiZWNhdXNlIHJhc3RlciB0aWxlcyBhcmVuJ3QgY2xpcHBlZCB3aGVuIHJlbmRlcmluZy5cbiAgICAgICAgICovXG4gICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcbiAgICAgICAgdmFyIGNvb3JkcyA9IHRoaXMuY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uKGxhdGxuZykge1xuICAgICAgICAgICAgdmFyIGxvYyA9IExhdExuZy5jb252ZXJ0KGxhdGxuZyk7XG4gICAgICAgICAgICByZXR1cm4gbWFwLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUobG9jKS56b29tVG8oMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtaW5YID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtaW5ZID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtYXhYID0gLUluZmluaXR5O1xuICAgICAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGR4ID0gbWF4WCAtIG1pblg7XG4gICAgICAgIHZhciBkeSA9IG1heFkgLSBtaW5ZO1xuICAgICAgICB2YXIgZE1heCA9IE1hdGgubWF4KGR4LCBkeSk7XG4gICAgICAgIHZhciBjZW50ZXIgPSBuZXcgQ29vcmRpbmF0ZSgobWluWCArIG1heFgpIC8gMiwgKG1pblkgKyBtYXhZKSAvIDIsIDApXG4gICAgICAgICAgICAuem9vbVRvKE1hdGguZmxvb3IoLU1hdGgubG9nKGRNYXgpIC8gTWF0aC5MTjIpKTtcblxuICAgICAgICB2YXIgdGlsZUV4dGVudCA9IDQwOTY7XG4gICAgICAgIHZhciB0aWxlQ29vcmRzID0gY29vcmRzLm1hcChmdW5jdGlvbihjb29yZCkge1xuICAgICAgICAgICAgdmFyIHpvb21lZENvb3JkID0gY29vcmQuem9vbVRvKGNlbnRlci56b29tKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZCgoem9vbWVkQ29vcmQuY29sdW1uIC0gY2VudGVyLmNvbHVtbikgKiB0aWxlRXh0ZW50KSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKCh6b29tZWRDb29yZC5yb3cgLSBjZW50ZXIucm93KSAqIHRpbGVFeHRlbnQpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGdsID0gbWFwLnBhaW50ZXIuZ2w7XG4gICAgICAgIHZhciBtYXhJbnQxNiA9IDMyNzY3O1xuICAgICAgICB2YXIgYXJyYXkgPSBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICB0aWxlQ29vcmRzWzBdLngsIHRpbGVDb29yZHNbMF0ueSwgMCwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMV0ueCwgdGlsZUNvb3Jkc1sxXS55LCBtYXhJbnQxNiwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbM10ueCwgdGlsZUNvb3Jkc1szXS55LCAwLCBtYXhJbnQxNixcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMl0ueCwgdGlsZUNvb3Jkc1syXS55LCBtYXhJbnQxNiwgbWF4SW50MTZcbiAgICAgICAgXSk7XG5cbiAgICAgICAgdGhpcy50aWxlID0gbmV3IFRpbGUoKTtcbiAgICAgICAgdGhpcy50aWxlLmJ1Y2tldHMgPSB7fTtcblxuICAgICAgICB0aGlzLnRpbGUuYm91bmRzQnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGUuYm91bmRzQnVmZmVyKTtcbiAgICAgICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGFycmF5LCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgdGhpcy5jZW50ZXIgPSBjZW50ZXI7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvICYmIHRoaXMudmlkZW8ucmVhZHlTdGF0ZSA+PSAyO1xuICAgIH0sXG5cbiAgICB1cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBub29wXG4gICAgfSxcblxuICAgIHJlbmRlcjogZnVuY3Rpb24obGF5ZXJzLCBwYWludGVyKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnZpZGVvLnJlYWR5U3RhdGUgPCAyKSByZXR1cm47IC8vIG5vdCBlbm91Z2ggZGF0YSBmb3IgY3VycmVudCBwb3NpdGlvblxuXG4gICAgICAgIHZhciBjID0gdGhpcy5jZW50ZXI7XG4gICAgICAgIHRoaXMudGlsZS5jYWxjdWxhdGVNYXRyaWNlcyhjLnpvb20sIGMuY29sdW1uLCBjLnJvdywgdGhpcy5tYXAudHJhbnNmb3JtLCBwYWludGVyKTtcblxuICAgICAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuICAgICAgICBpZiAoIXRoaXMudGlsZS50ZXh0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLnRpbGUudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLnZpZGVvKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy52aWRlbyk7XG4gICAgICAgIH1cblxuICAgICAgICBwYWludGVyLmRyYXdMYXllcnMobGF5ZXJzLCB0aGlzLnRpbGUucG9zTWF0cml4LCB0aGlzLnRpbGUpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihwb2ludCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQWN0b3IgPSByZXF1aXJlKCcuLi91dGlsL2FjdG9yJyk7XG52YXIgV29ya2VyVGlsZSA9IHJlcXVpcmUoJy4vd29ya2VyX3RpbGUnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIHZ0ID0gcmVxdWlyZSgndmVjdG9yLXRpbGUnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG52YXIgZ2VvanNvbnZ0ID0gcmVxdWlyZSgnZ2VvanNvbi12dCcpO1xudmFyIEdlb0pTT05XcmFwcGVyID0gcmVxdWlyZSgnLi9nZW9qc29uX3dyYXBwZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWxmKSB7XG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoc2VsZik7XG59O1xuXG5mdW5jdGlvbiBXb3JrZXIoc2VsZikge1xuICAgIHRoaXMuc2VsZiA9IHNlbGY7XG4gICAgdGhpcy5hY3RvciA9IG5ldyBBY3RvcihzZWxmLCB0aGlzKTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcblxuICAgIHRoaXMubG9hZGVkID0ge307XG4gICAgdGhpcy5sYXllcnMgPSBbXTtcbiAgICB0aGlzLmdlb0pTT05JbmRleGVzID0ge307XG59XG5cbnV0aWwuZXh0ZW5kKFdvcmtlci5wcm90b3R5cGUsIHtcbiAgICAnc2V0IGxheWVycyc6IGZ1bmN0aW9uKGxheWVycykge1xuICAgICAgICB0aGlzLmxheWVycyA9IGxheWVycztcbiAgICB9LFxuXG4gICAgJ2xvYWQgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHBhcmFtcy5zb3VyY2UsXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmICghdGhpcy5sb2FkaW5nW3NvdXJjZV0pXG4gICAgICAgICAgICB0aGlzLmxvYWRpbmdbc291cmNlXSA9IHt9O1xuXG5cbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLmxvYWRpbmdbc291cmNlXVt1aWRdID0gbmV3IFdvcmtlclRpbGUocGFyYW1zKTtcblxuICAgICAgICB0aWxlLnhociA9IGFqYXguZ2V0QXJyYXlCdWZmZXIocGFyYW1zLnVybCwgZG9uZS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBmdW5jdGlvbiBkb25lKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9hZGluZ1tzb3VyY2VdW3VpZF07XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgICAgICB0aWxlLmRhdGEgPSBuZXcgdnQuVmVjdG9yVGlsZShuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIHRpbGUucGFyc2UodGlsZS5kYXRhLCB0aGlzLmxheWVycywgdGhpcy5hY3RvciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRlZFtzb3VyY2VdID0gdGhpcy5sb2FkZWRbc291cmNlXSB8fCB7fTtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bdWlkXSA9IHRpbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbG9hZCB0aWxlJzogZnVuY3Rpb24ocGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgbG9hZGVkID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGVkICYmIGxvYWRlZFt1aWRdKSB7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IGxvYWRlZFt1aWRdO1xuICAgICAgICAgICAgdGlsZS5wYXJzZSh0aWxlLmRhdGEsIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2Fib3J0IHRpbGUnOiBmdW5jdGlvbihwYXJhbXMpIHtcbiAgICAgICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGluZyAmJiBsb2FkaW5nW3VpZF0pIHtcbiAgICAgICAgICAgIGxvYWRpbmdbdWlkXS54aHIuYWJvcnQoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkaW5nW3VpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbW92ZSB0aWxlJzogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIHVpZCA9IHBhcmFtcy51aWQ7XG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkZWRbdWlkXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAncmVkbyBwbGFjZW1lbnQnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gbG9hZGVkW3VpZF07XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGlsZS5yZWRvUGxhY2VtZW50KHBhcmFtcy5hbmdsZSwgcGFyYW1zLnBpdGNoLCBwYXJhbXMuY29sbGlzaW9uRGVidWcpO1xuXG4gICAgICAgICAgICBpZiAocmVzdWx0LnJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdC5yZXN1bHQsIHJlc3VsdC50cmFuc2ZlcmFibGVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2UgaWYgKGxvYWRpbmcgJiYgbG9hZGluZ1t1aWRdKSB7XG4gICAgICAgICAgICBsb2FkaW5nW3VpZF0uYW5nbGUgPSBwYXJhbXMuYW5nbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3BhcnNlIGdlb2pzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBpbmRleERhdGEgPSBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgdGhpcy5nZW9KU09OSW5kZXhlc1twYXJhbXMuc291cmNlXSA9IGdlb2pzb252dChkYXRhLCB7YmFzZVpvb206IHBhcmFtcy5tYXhab29tfSk7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIC8vIFRPRE8gYWNjZXB0IHBhcmFtcy51cmwgZm9yIHVybHMgaW5zdGVhZFxuXG4gICAgICAgIC8vIE5vdCwgYmVjYXVzZSBvZiBzYW1lIG9yaWdpbiBpc3N1ZXMsIHVybHMgbXVzdCBlaXRoZXIgaW5jbHVkZSBhblxuICAgICAgICAvLyBleHBsaWNpdCBvcmlnaW4gb3IgYWJzb2x1dGUgcGF0aC5cbiAgICAgICAgLy8gaWU6IC9mb28vYmFyLmpzb24gb3IgaHR0cDovL2V4YW1wbGUuY29tL2Jhci5qc29uXG4gICAgICAgIC8vIGJ1dCBub3QgLi4vZm9vL2Jhci5qc29uXG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zLmRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBhamF4LmdldEpTT04ocGFyYW1zLmRhdGEsIGluZGV4RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpbmRleERhdGEobnVsbCwgcGFyYW1zLmRhdGEpO1xuICAgIH0sXG5cbiAgICAnbG9hZCBnZW9qc29uIHRpbGUnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwYXJhbXMuc291cmNlLFxuICAgICAgICAgICAgY29vcmQgPSBwYXJhbXMuY29vcmQ7XG5cbiAgICAgICAgLy8gY29uc29sZS50aW1lKCd0aWxlICcgKyBjb29yZC56ICsgJyAnICsgY29vcmQueCArICcgJyArIGNvb3JkLnkpO1xuXG4gICAgICAgIHZhciBnZW9KU09OVGlsZSA9IHRoaXMuZ2VvSlNPTkluZGV4ZXNbc291cmNlXS5nZXRUaWxlKGNvb3JkLnosIGNvb3JkLngsIGNvb3JkLnkpO1xuXG4gICAgICAgIC8vIGNvbnNvbGUudGltZUVuZCgndGlsZSAnICsgY29vcmQueiArICcgJyArIGNvb3JkLnggKyAnICcgKyBjb29yZC55KTtcblxuICAgICAgICAvLyBpZiAoIWdlb0pTT05UaWxlKSBjb25zb2xlLmxvZygnbm90IGZvdW5kJywgdGhpcy5nZW9KU09OSW5kZXhlc1tzb3VyY2VdLCBjb29yZCk7XG5cbiAgICAgICAgaWYgKCFnZW9KU09OVGlsZSkgcmV0dXJuIGNhbGxiYWNrKG51bGwsIG51bGwpOyAvLyBub3RoaW5nIGluIHRoZSBnaXZlbiB0aWxlXG5cbiAgICAgICAgdmFyIHRpbGUgPSBuZXcgV29ya2VyVGlsZShwYXJhbXMpO1xuICAgICAgICB0aWxlLnBhcnNlKG5ldyBHZW9KU09OV3JhcHBlcihnZW9KU09OVGlsZS5mZWF0dXJlcyksIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG5cbiAgICAgICAgdGhpcy5sb2FkZWRbc291cmNlXSA9IHRoaXMubG9hZGVkW3NvdXJjZV0gfHwge307XG4gICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bcGFyYW1zLnVpZF0gPSB0aWxlO1xuICAgIH0sXG5cbiAgICAncXVlcnkgZmVhdHVyZXMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB0aWxlID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0gJiYgdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV1bcGFyYW1zLnVpZF07XG4gICAgICAgIGlmICh0aWxlKSB7XG4gICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLnF1ZXJ5KHBhcmFtcywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgW10pO1xuICAgICAgICB9XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBGZWF0dXJlVHJlZSA9IHJlcXVpcmUoJy4uL2RhdGEvZmVhdHVyZV90cmVlJyk7XG52YXIgQ29sbGlzaW9uID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl90aWxlJyk7XG52YXIgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyX3NldCcpO1xudmFyIGNyZWF0ZUJ1Y2tldCA9IHJlcXVpcmUoJy4uL2RhdGEvY3JlYXRlX2J1Y2tldCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlclRpbGU7XG5cbmZ1bmN0aW9uIFdvcmtlclRpbGUocGFyYW1zKSB7XG4gICAgdGhpcy5jb29yZCA9IHBhcmFtcy5jb29yZDtcbiAgICB0aGlzLnVpZCA9IHBhcmFtcy51aWQ7XG4gICAgdGhpcy56b29tID0gcGFyYW1zLnpvb207XG4gICAgdGhpcy5tYXhab29tID0gcGFyYW1zLm1heFpvb207XG4gICAgdGhpcy50aWxlU2l6ZSA9IHBhcmFtcy50aWxlU2l6ZTtcbiAgICB0aGlzLnNvdXJjZSA9IHBhcmFtcy5zb3VyY2U7XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IHBhcmFtcy5vdmVyc2NhbGluZztcbiAgICB0aGlzLmFuZ2xlID0gcGFyYW1zLmFuZ2xlO1xuICAgIHRoaXMucGl0Y2ggPSBwYXJhbXMucGl0Y2g7XG4gICAgdGhpcy5jb2xsaXNpb25EZWJ1ZyA9IHBhcmFtcy5jb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3RhY2tzID0ge307XG59XG5cbldvcmtlclRpbGUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oZGF0YSwgbGF5ZXJzLCBhY3RvciwgY2FsbGJhY2spIHtcblxuICAgIHRoaXMuc3RhdHVzID0gJ3BhcnNpbmcnO1xuXG4gICAgdGhpcy5mZWF0dXJlVHJlZSA9IG5ldyBGZWF0dXJlVHJlZSh0aGlzLmNvb3JkLCB0aGlzLm92ZXJzY2FsaW5nKTtcblxuICAgIHZhciBpLCBrLFxuICAgICAgICB0aWxlID0gdGhpcyxcbiAgICAgICAgbGF5ZXIsXG4gICAgICAgIGJ1Y2tldCxcbiAgICAgICAgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoKSxcbiAgICAgICAgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb24gPSBuZXcgQ29sbGlzaW9uKHRoaXMuem9vbSwgNDA5NiwgdGhpcy50aWxlU2l6ZSksXG4gICAgICAgIGJ1Y2tldHMgPSB7fSxcbiAgICAgICAgYnVja2V0c0luT3JkZXIgPSB0aGlzLmJ1Y2tldHNJbk9yZGVyID0gW10sXG4gICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyID0ge307XG5cbiAgICBjb2xsaXNpb24ucmVzZXQodGhpcy5hbmdsZSwgdGhpcy5waXRjaCk7XG5cbiAgICAvLyBNYXAgbm9uLXJlZiBsYXllcnMgdG8gYnVja2V0cy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKGxheWVyLnJlZilcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBtaW56b29tID0gbGF5ZXIubWluem9vbTtcbiAgICAgICAgaWYgKG1pbnpvb20gJiYgdGhpcy56b29tIDwgbWluem9vbSAmJiBtaW56b29tIDwgdGhpcy5tYXhab29tKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIG1heHpvb20gPSBsYXllci5tYXh6b29tO1xuICAgICAgICBpZiAobWF4em9vbSAmJiB0aGlzLnpvb20gPj0gbWF4em9vbSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2aXNpYmlsaXR5ID0gbGF5ZXIubGF5b3V0LnZpc2liaWxpdHk7XG4gICAgICAgIGlmICh2aXNpYmlsaXR5ID09PSAnbm9uZScpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgdGhpcy56b29tLCB0aGlzLm92ZXJzY2FsaW5nLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbiAgICAgICAgYnVja2V0LmxheWVycyA9IFtsYXllci5pZF07XG5cbiAgICAgICAgYnVja2V0c1tidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICBidWNrZXRzSW5PcmRlci5wdXNoKGJ1Y2tldCk7XG5cbiAgICAgICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgICAgICB2YXIgc291cmNlTGF5ZXIgPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXSlcbiAgICAgICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltzb3VyY2VMYXllcl0gPSB7fTtcbiAgICAgICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXVtidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZ2VvanNvbiB0aWxlXG4gICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5kZXggcmVmIGxheWVycy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKCFsYXllci5yZWYpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBidWNrZXRzW2xheWVyLnJlZl07XG4gICAgICAgIGlmICghYnVja2V0KVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgYnVja2V0LmxheWVycy5wdXNoKGxheWVyLmlkKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0ZW50ID0gNDA5NjtcblxuICAgIC8vIHJlYWQgZWFjaCBsYXllciwgYW5kIHNvcnQgaXRzIGZlYXR1cmVzIGludG8gYnVja2V0c1xuICAgIGlmIChkYXRhLmxheWVycykge1xuICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgIGZvciAoayBpbiBidWNrZXRzQnlTb3VyY2VMYXllcikge1xuICAgICAgICAgICAgbGF5ZXIgPSBkYXRhLmxheWVyc1trXTtcbiAgICAgICAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGxheWVyLmV4dGVudCkgZXh0ZW50ID0gbGF5ZXIuZXh0ZW50O1xuICAgICAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMobGF5ZXIsIGJ1Y2tldHNCeVNvdXJjZUxheWVyW2tdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdlb2pzb25cbiAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMoZGF0YSwgYnVja2V0c0J5U291cmNlTGF5ZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNvcnRMYXllckludG9CdWNrZXRzKGxheWVyLCBidWNrZXRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBmZWF0dXJlID0gbGF5ZXIuZmVhdHVyZShpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBidWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0LmZpbHRlcihmZWF0dXJlKSkge1xuICAgICAgICAgICAgICAgICAgICBidWNrZXQuZmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcHJldlBsYWNlbWVudEJ1Y2tldDtcbiAgICB2YXIgcmVtYWluaW5nID0gYnVja2V0c0luT3JkZXIubGVuZ3RoO1xuXG4gICAgLypcbiAgICAgKiAgVGhlIGFzeW5jIHBhcnNpbmcgaGVyZSBpcyBhIGJpdCB0cmlja3kuXG4gICAgICogIFNvbWUgYnVja2V0cyBkZXBlbmQgb24gcmVzb3VyY2VzIHRoYXQgbWF5IG5lZWQgdG8gYmUgbG9hZGVkIGFzeW5jIChnbHlwaHMpLlxuICAgICAqICBTb21lIGJ1Y2tldHMgbmVlZCB0byBiZSBwYXJzZWQgaW4gb3JkZXIgKHRvIGdldCBjb2xsaXNpb24gcHJpb3JpdGllcyByaWdodCkuXG4gICAgICpcbiAgICAgKiAgRGVwZW5kZW5jaWVzIGNhbGxzIGFyZSBpbml0aWF0ZWQgZmlyc3QgdG8gZ2V0IHRob3NlIHJvbGxpbmcuXG4gICAgICogIEJ1Y2tldHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlciwgYXJlbid0IHRvIHNhdmUgdGltZS5cbiAgICAgKi9cblxuICAgIGZvciAoaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWNrZXQgPSBidWNrZXRzSW5PcmRlcltpXTtcblxuICAgICAgICAvLyBMaW5rIGJ1Y2tldHMgdGhhdCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlclxuICAgICAgICBpZiAoYnVja2V0LmNvbGxpc2lvbikge1xuICAgICAgICAgICAgaWYgKHByZXZQbGFjZW1lbnRCdWNrZXQpIHtcbiAgICAgICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0Lm5leHQgPSBidWNrZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Y2tldC5wcmV2aW91c1BsYWNlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0ID0gYnVja2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5nZXREZXBlbmRlbmNpZXModGhpcywgYWN0b3IsIGRlcGVuZGVuY2llc0RvbmUoYnVja2V0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbW1lZGlhdGVseSBwYXJzZSBidWNrZXRzIHdoZXJlIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGFuZCBubyBkZXBlbmRlbmNpZXNcbiAgICAgICAgaWYgKCFidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQuZ2V0RGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVwZW5kZW5jaWVzRG9uZShidWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgYnVja2V0LmRlcGVuZGVuY2llc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQsIGVycik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VCdWNrZXQodGlsZSwgYnVja2V0LCBza2lwKSB7XG4gICAgICAgIGlmIChidWNrZXQuZ2V0RGVwZW5kZW5jaWVzICYmICFidWNrZXQuZGVwZW5kZW5jaWVzTG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmIChidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQucHJldmlvdXNQbGFjZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoIXNraXApIHtcbiAgICAgICAgICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5mZWF0dXJlcy5sZW5ndGgpIGJ1Y2tldC5hZGRGZWF0dXJlcygpO1xuICAgICAgICAgICAgdmFyIHRpbWUgPSBEYXRlLm5vdygpIC0gbm93O1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0LmZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmZWF0dXJlID0gYnVja2V0LmZlYXR1cmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLmluc2VydChmZWF0dXJlLmJib3goKSwgYnVja2V0LmxheWVycywgZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMgPSBzZWxmLmJ1Y2tldFN0YXRzIHx8IHtfdG90YWw6IDB9O1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMuX3RvdGFsICs9IHRpbWU7XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0c1tidWNrZXQuaWRdID0gKHNlbGYuYnVja2V0U3RhdHNbYnVja2V0LmlkXSB8fCAwKSArIHRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZW1haW5pbmctLTtcblxuICAgICAgICBpZiAoIXJlbWFpbmluZykge1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJ5IHBhcnNpbmcgdGhlIG5leHQgYnVja2V0LCBpZiBpdCBpcyByZWFkeVxuICAgICAgICBpZiAoYnVja2V0Lm5leHQpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5uZXh0LnByZXZpb3VzUGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldC5uZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbmUoKSB7XG5cbiAgICAgICAgdGlsZS5zdGF0dXMgPSAnZG9uZSc7XG5cbiAgICAgICAgaWYgKHRpbGUucmVkb1BsYWNlbWVudEFmdGVyRG9uZSkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRpbGUucmVkb1BsYWNlbWVudCh0aWxlLmFuZ2xlLCB0aWxlLnBpdGNoKS5yZXN1bHQ7XG4gICAgICAgICAgICBidWZmZXJzLmdseXBoVmVydGV4ID0gcmVzdWx0LmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgICAgICBidWZmZXJzLmljb25WZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5pY29uVmVydGV4O1xuICAgICAgICAgICAgYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhbnNmZXJhYmxlcyA9IFtdLFxuICAgICAgICAgICAgZWxlbWVudEdyb3VwcyA9IHt9O1xuXG4gICAgICAgIGZvciAoayBpbiBidWZmZXJzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlcmFibGVzLnB1c2goYnVmZmVyc1trXS5hcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGsgaW4gYnVja2V0cykge1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1trXSA9IGJ1Y2tldHNba10uZWxlbWVudEdyb3VwcztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cHM6IGVsZW1lbnRHcm91cHMsXG4gICAgICAgICAgICBidWZmZXJzOiBidWZmZXJzLFxuICAgICAgICAgICAgZXh0ZW50OiBleHRlbnRcbiAgICAgICAgfSwgdHJhbnNmZXJhYmxlcyk7XG4gICAgfVxufTtcblxuV29ya2VyVGlsZS5wcm90b3R5cGUucmVkb1BsYWNlbWVudCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCwgY29sbGlzaW9uRGVidWcpIHtcblxuICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gJ2RvbmUnKSB7XG4gICAgICAgIHRoaXMucmVkb1BsYWNlbWVudEFmdGVyRG9uZSA9IHRydWU7XG4gICAgICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHZhciBidWZmZXJzID0gbmV3IEJ1ZmZlclNldCgpO1xuICAgIHZhciB0cmFuc2ZlcmFibGVzID0gW107XG4gICAgdmFyIGVsZW1lbnRHcm91cHMgPSB7fTtcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICBjb2xsaXNpb24ucmVzZXQoYW5nbGUsIHBpdGNoKTtcblxuICAgIHZhciBidWNrZXRzSW5PcmRlciA9IHRoaXMuYnVja2V0c0luT3JkZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYnVja2V0ID0gYnVja2V0c0luT3JkZXJbaV07XG5cbiAgICAgICAgaWYgKGJ1Y2tldC50eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgYnVja2V0LnBsYWNlRmVhdHVyZXMoYnVmZmVycywgY29sbGlzaW9uRGVidWcpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1tidWNrZXQuaWRdID0gYnVja2V0LmVsZW1lbnRHcm91cHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBrIGluIGJ1ZmZlcnMpIHtcbiAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGJ1ZmZlcnNba10uYXJyYXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHJlc3VsdDoge1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwczogZWxlbWVudEdyb3VwcyxcbiAgICAgICAgICAgIGJ1ZmZlcnM6IGJ1ZmZlcnNcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmZXJhYmxlczogdHJhbnNmZXJhYmxlc1xuICAgIH07XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQW5pbWF0aW9uTG9vcDtcblxuZnVuY3Rpb24gQW5pbWF0aW9uTG9vcCgpIHtcbiAgICB0aGlzLm4gPSAwO1xuICAgIHRoaXMudGltZXMgPSBbXTtcbn1cblxuLy8gQXJlIGFsbCBhbmltYXRpb25zIGRvbmU/XG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5zdG9wcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQudGltZSA+PSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgIH0pO1xuICAgIHJldHVybiAhdGhpcy50aW1lcy5sZW5ndGg7XG59O1xuXG4vLyBBZGQgYSBuZXcgYW5pbWF0aW9uIHRoYXQgd2lsbCBydW4gdCBtaWxsaXNlY29uZHNcbi8vIFJldHVybnMgYW4gaWQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgaXQgbGF5ZXJcbkFuaW1hdGlvbkxvb3AucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aGlzLnRpbWVzLnB1c2goeyBpZDogdGhpcy5uLCB0aW1lOiB0ICsgKG5ldyBEYXRlKCkpLmdldFRpbWUoKSB9KTtcbiAgICByZXR1cm4gdGhpcy5uKys7XG59O1xuXG4vLyBDYW5jZWwgYW4gYW5pbWF0aW9uXG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbihuKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQuaWQgIT09IG47XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSW1hZ2VTcHJpdGU7XG5cbmZ1bmN0aW9uIEltYWdlU3ByaXRlKGJhc2UpIHtcbiAgICB0aGlzLmJhc2UgPSBiYXNlO1xuICAgIHRoaXMucmV0aW5hID0gYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMTtcblxuICAgIGJhc2UgPSB0aGlzLmJhc2UgKyAodGhpcy5yZXRpbmEgPyAnQDJ4JyA6ICcnKTtcblxuICAgIGFqYXguZ2V0SlNPTihiYXNlICsgJy5qc29uJywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgaWYgKHRoaXMuaW1nKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgYWpheC5nZXRJbWFnZShiYXNlICsgJy5wbmcnLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByZW11bHRpcGx5IHRoZSBzcHJpdGVcbiAgICAgICAgdmFyIGRhdGEgPSBpbWcuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgbmV3ZGF0YSA9IGltZy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgICAgICAgIHZhciBhbHBoYSA9IGRhdGFbaSArIDNdIC8gMjU1O1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMF0gPSBkYXRhW2kgKyAwXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMV0gPSBkYXRhW2kgKyAxXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMl0gPSBkYXRhW2kgKyAyXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgM10gPSBkYXRhW2kgKyAzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW1nID0gaW1nO1xuICAgICAgICBpZiAodGhpcy5kYXRhKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5sb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gISEodGhpcy5kYXRhICYmIHRoaXMuaW1nKTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbigvKmdsKi8pIHtcbiAgICBpZiAoYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMSAhPT0gdGhpcy5yZXRpbmEpIHtcbiAgICAgICAgdmFyIG5ld1Nwcml0ZSA9IG5ldyBJbWFnZVNwcml0ZSh0aGlzLmJhc2UpO1xuICAgICAgICBuZXdTcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuaW1nID0gbmV3U3ByaXRlLmltZztcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ld1Nwcml0ZS5kYXRhO1xuICAgICAgICAgICAgdGhpcy5yZXRpbmEgPSBuZXdTcHJpdGUucmV0aW5hO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIFNwcml0ZVBvc2l0aW9uKCkge31cblNwcml0ZVBvc2l0aW9uLnByb3RvdHlwZSA9IHsgeDogMCwgeTogMCwgd2lkdGg6IDAsIGhlaWdodDogMCwgcGl4ZWxSYXRpbzogMSwgc2RmOiBmYWxzZSB9O1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUuZ2V0U3ByaXRlUG9zaXRpb24gPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCgpKSByZXR1cm4gbmV3IFNwcml0ZVBvc2l0aW9uKCk7XG5cbiAgICB2YXIgcG9zID0gdGhpcy5kYXRhICYmIHRoaXMuZGF0YVtuYW1lXTtcbiAgICBpZiAocG9zICYmIHRoaXMuaW1nKSByZXR1cm4gcG9zO1xuXG4gICAgcmV0dXJuIG5ldyBTcHJpdGVQb3NpdGlvbigpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge307XG5cbnJlZmVyZW5jZS5sYXlvdXQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BzKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIHRoaXNbcF0gPSBwcm9wc1twXTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHByb3AgaW4gcHJvcGVydGllcykge1xuICAgICAgICBpZiAocHJvcGVydGllc1twcm9wXS5kZWZhdWx0ID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBQcm9wZXJ0aWVzLnByb3RvdHlwZVtwcm9wXSA9IHByb3BlcnRpZXNbcHJvcF0uZGVmYXVsdDtcbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHNbY2xhc3NOYW1lLnJlcGxhY2UoJ2xheW91dF8nLCAnJyldID0gUHJvcGVydGllcztcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi9yZWZlcmVuY2UnKTtcbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5yZWZlcmVuY2UucGFpbnQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgQ2FsY3VsYXRlZCA9IGZ1bmN0aW9uKCkge307XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcykge1xuICAgICAgICB2YXIgcHJvcCA9IHByb3BlcnRpZXNbcF0sXG4gICAgICAgICAgICB2YWx1ZSA9IHByb3AuZGVmYXVsdDtcblxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgICAgIGlmIChwcm9wLnR5cGUgPT09ICdjb2xvcicpIHZhbHVlID0gcGFyc2VDU1NDb2xvcih2YWx1ZSk7XG5cbiAgICAgICAgQ2FsY3VsYXRlZC5wcm90b3R5cGVbcF0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBDYWxjdWxhdGVkLnByb3RvdHlwZS5oaWRkZW4gPSBmYWxzZTtcbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgncGFpbnRfJywgJycpXSA9IENhbGN1bGF0ZWQ7XG59KTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4uL3NvdXJjZS9zb3VyY2UnKTtcbnZhciBTdHlsZUxheWVyID0gcmVxdWlyZSgnLi9zdHlsZV9sYXllcicpO1xudmFyIEltYWdlU3ByaXRlID0gcmVxdWlyZSgnLi9pbWFnZV9zcHJpdGUnKTtcbnZhciBHbHlwaFNvdXJjZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nbHlwaF9zb3VyY2UnKTtcbnZhciBHbHlwaEF0bGFzID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoX2F0bGFzJyk7XG52YXIgU3ByaXRlQXRsYXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvc3ByaXRlX2F0bGFzJyk7XG52YXIgTGluZUF0bGFzID0gcmVxdWlyZSgnLi4vcmVuZGVyL2xpbmVfYXRsYXMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplU3R5bGVVUkw7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi91dGlsL2Rpc3BhdGNoZXInKTtcbnZhciBBbmltYXRpb25Mb29wID0gcmVxdWlyZSgnLi9hbmltYXRpb25fbG9vcCcpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvbGliL3ZhbGlkYXRlL2xhdGVzdCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlO1xuXG5mdW5jdGlvbiBTdHlsZShzdHlsZXNoZWV0LCBhbmltYXRpb25Mb29wKSB7XG4gICAgdGhpcy5hbmltYXRpb25Mb29wID0gYW5pbWF0aW9uTG9vcCB8fCBuZXcgQW5pbWF0aW9uTG9vcCgpO1xuICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKE1hdGgubWF4KGJyb3dzZXIuaGFyZHdhcmVDb25jdXJyZW5jeSAtIDEsIDEpLCB0aGlzKTtcbiAgICB0aGlzLmdseXBoQXRsYXMgPSBuZXcgR2x5cGhBdGxhcygxMDI0LCAxMDI0KTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzID0gbmV3IFNwcml0ZUF0bGFzKDUxMiwgNTEyKTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzLnJlc2l6ZShicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIHRoaXMubGluZUF0bGFzID0gbmV3IExpbmVBdGxhcygyNTYsIDUxMik7XG5cbiAgICB0aGlzLl9sYXllcnMgPSB7fTtcbiAgICB0aGlzLl9vcmRlciAgPSBbXTtcbiAgICB0aGlzLl9ncm91cHMgPSBbXTtcbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcblxuICAgIHRoaXMuem9vbUhpc3RvcnkgPSB7fTtcblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFNvdXJjZUV2ZW50JyxcbiAgICAgICAgJ19mb3J3YXJkVGlsZUV2ZW50JyxcbiAgICAgICAgJ19yZWRvUGxhY2VtZW50J1xuICAgIF0sIHRoaXMpO1xuXG4gICAgdmFyIGxvYWRlZCA9IGZ1bmN0aW9uKGVyciwgc3R5bGVzaGVldCkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKHN0eWxlc2hlZXQpO1xuICAgICAgICBpZiAodmFsaWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YWxpZC5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fbG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHlsZXNoZWV0ID0gc3R5bGVzaGVldDtcblxuICAgICAgICB2YXIgc291cmNlcyA9IHN0eWxlc2hlZXQuc291cmNlcztcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gc291cmNlcykge1xuICAgICAgICAgICAgdGhpcy5hZGRTb3VyY2UoaWQsIHNvdXJjZXNbaWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHlsZXNoZWV0LnNwcml0ZSkge1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUgPSBuZXcgSW1hZ2VTcHJpdGUoc3R5bGVzaGVldC5zcHJpdGUpO1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUub24oJ2xvYWQnLCB0aGlzLmZpcmUuYmluZCh0aGlzLCAnY2hhbmdlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZSA9IG5ldyBHbHlwaFNvdXJjZShzdHlsZXNoZWV0LmdseXBocywgdGhpcy5nbHlwaEF0bGFzKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBpZiAodHlwZW9mIHN0eWxlc2hlZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTihub3JtYWxpemVVUkwoc3R5bGVzaGVldCksIGxvYWRlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnJvd3Nlci5mcmFtZShsb2FkZWQuYmluZCh0aGlzLCBudWxsLCBzdHlsZXNoZWV0KSk7XG4gICAgfVxufVxuXG5TdHlsZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKVxuICAgICAgICAgICAgaWYgKCF0aGlzLnNvdXJjZXNbaWRdLmxvYWRlZCgpKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAodGhpcy5zcHJpdGUgJiYgIXRoaXMuc3ByaXRlLmxvYWRlZCgpKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBfcmVzb2x2ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBpZCwgbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5fbGF5ZXJzID0ge307XG4gICAgICAgIHRoaXMuX29yZGVyICA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zdHlsZXNoZWV0LmxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGF5ZXIgPSBuZXcgU3R5bGVMYXllcih0aGlzLnN0eWxlc2hlZXQubGF5ZXJzW2ldLCB0aGlzLnN0eWxlc2hlZXQuY29uc3RhbnRzIHx8IHt9KTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgICAgIHRoaXMuX29yZGVyLnB1c2gobGF5ZXIuaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsYXlvdXQgcHJvcGVydGllcy5cbiAgICAgICAgZm9yIChpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZUxheW91dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSByZWZlcmVuY2UgYW5kIHBhaW50IHByb3BlcnRpZXMuXG4gICAgICAgIGZvciAoaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLnJlc29sdmVSZWZlcmVuY2UodGhpcy5fbGF5ZXJzKTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZVBhaW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICB9LFxuXG4gICAgX2dyb3VwTGF5ZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdyb3VwO1xuXG4gICAgICAgIHRoaXMuX2dyb3VwcyA9IFtdO1xuXG4gICAgICAgIC8vIFNwbGl0IGludG8gZ3JvdXBzIG9mIGNvbnNlY3V0aXZlIHRvcC1sZXZlbCBsYXllcnMgd2l0aCB0aGUgc2FtZSBzb3VyY2UuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fb3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1t0aGlzLl9vcmRlcltpXV07XG5cbiAgICAgICAgICAgIGlmICghZ3JvdXAgfHwgbGF5ZXIuc291cmNlICE9PSBncm91cC5zb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwLnNvdXJjZSA9IGxheWVyLnNvdXJjZTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ncm91cHMucHVzaChncm91cCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdyb3VwLnB1c2gobGF5ZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9icm9hZGNhc3RMYXllcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb3JkZXJlZCA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgb3JkZXJlZC5wdXNoKHRoaXMuX2xheWVyc1tpZF0uanNvbigpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoJ3NldCBsYXllcnMnLCBvcmRlcmVkKTtcbiAgICB9LFxuXG4gICAgX2Nhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpIHJldHVybjtcblxuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLmNhc2NhZGUoY2xhc3Nlcywgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICB0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbiB8fCB7fSxcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICB9LFxuXG4gICAgX3JlY2FsY3VsYXRlOiBmdW5jdGlvbih6KSB7XG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuc291cmNlcylcbiAgICAgICAgICAgIHRoaXMuc291cmNlc1tpZF0udXNlZCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZVpvb21IaXN0b3J5KHopO1xuXG4gICAgICAgIHRoaXMucmFzdGVyRmFkZUR1cmF0aW9uID0gMzAwO1xuICAgICAgICBmb3IgKGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgdmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcblxuICAgICAgICAgICAgaWYgKGxheWVyLnJlY2FsY3VsYXRlKHosIHRoaXMuem9vbUhpc3RvcnkpICYmIGxheWVyLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1heFpvb21UcmFuc2l0aW9uRHVyYXRpb24gPSAzMDA7XG4gICAgICAgIGlmIChNYXRoLmZsb29yKHRoaXMueikgIT09IE1hdGguZmxvb3IoeikpIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uTG9vcC5zZXQobWF4Wm9vbVRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnogPSB6O1xuICAgICAgICB0aGlzLmZpcmUoJ3pvb20nKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVpvb21IaXN0b3J5OiBmdW5jdGlvbih6KSB7XG5cbiAgICAgICAgdmFyIHpoID0gdGhpcy56b29tSGlzdG9yeTtcblxuICAgICAgICBpZiAoemgubGFzdEludGVnZXJab29tID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGZpcnN0IHRpbWVcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbSA9IE1hdGguZmxvb3Ioeik7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb21UaW1lID0gMDtcbiAgICAgICAgICAgIHpoLmxhc3Rab29tID0gejtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgYW4gaW50ZWdlciB6b29tIGxldmVsIGFzIHBhc3NlZCBzaW5jZSB0aGUgbGFzdCBmcmFtZVxuICAgICAgICAvLyBhbmQgaWYgeWVzLCByZWNvcmQgaXQgd2l0aCB0aGUgdGltZS4gVXNlZCBmb3IgdHJhbnNpdGlvbmluZyBwYXR0ZXJucy5cbiAgICAgICAgaWYgKE1hdGguZmxvb3IoemgubGFzdFpvb20pIDwgTWF0aC5mbG9vcih6KSkge1xuICAgICAgICAgICAgemgubGFzdEludGVnZXJab29tID0gTWF0aC5mbG9vcih6KTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoTWF0aC5mbG9vcih6aC5sYXN0Wm9vbSkgPiBNYXRoLmZsb29yKHopKSB7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb20gPSBNYXRoLmZsb29yKHogKyAxKTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgemgubGFzdFpvb20gPSB6O1xuICAgIH0sXG5cbiAgICBhZGRTb3VyY2U6IGZ1bmN0aW9uKGlkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMuc291cmNlc1tpZF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBpcyBhbHJlYWR5IGEgc291cmNlIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIHNvdXJjZSA9IFNvdXJjZS5jcmVhdGUoc291cmNlKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2lkXSA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlLmlkID0gaWQ7XG4gICAgICAgIHNvdXJjZS5zdHlsZSA9IHRoaXM7XG4gICAgICAgIHNvdXJjZS5kaXNwYXRjaGVyID0gdGhpcy5kaXNwYXRjaGVyO1xuICAgICAgICBzb3VyY2UuZ2x5cGhBdGxhcyA9IHRoaXMuZ2x5cGhBdGxhcztcbiAgICAgICAgc291cmNlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCdjaGFuZ2UnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUucmVtb3ZlJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudCk7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLmFkZCcsIHtzb3VyY2U6IHNvdXJjZX0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgc291cmNlIGZyb20gdGhpcyBzdHlsZXNoZWV0LCBnaXZlbiBpdHMgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBzb3VyY2UgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMge1N0eWxlfSB0aGlzIHN0eWxlXG4gICAgICogQHRocm93cyB7RXJyb3J9IGlmIG5vIHNvdXJjZSBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlU291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHNvdXJjZSB3aXRoIHRoaXMgSUQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgIHNvdXJjZVxuICAgICAgICAgICAgLm9mZignbG9hZCcsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZignY2hhbmdlJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5hZGQnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ3RpbGUuZXJyb3InLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KTtcbiAgICAgICAgdGhpcy5maXJlKCdzb3VyY2UucmVtb3ZlJywge3NvdXJjZTogc291cmNlfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzb3VyY2UgYnkgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBkZXNpcmVkIHNvdXJjZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHNvdXJjZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0U291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgbGF5ZXIgdG8gdGhlIG1hcCBzdHlsZS4gVGhlIGxheWVyIHdpbGwgYmUgaW5zZXJ0ZWQgYmVmb3JlIHRoZSBsYXllciB3aXRoXG4gICAgICogSUQgYGJlZm9yZWAsIG9yIGFwcGVuZGVkIGlmIGBiZWZvcmVgIGlzIG9taXR0ZWQuXG4gICAgICogQHBhcmFtIHtTdHlsZUxheWVyfE9iamVjdH0gbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGJlZm9yZSAgSUQgb2YgYW4gZXhpc3RpbmcgbGF5ZXIgdG8gaW5zZXJ0IGJlZm9yZVxuICAgICAqIEBmaXJlcyBsYXllci5hZGRcbiAgICAgKiBAcmV0dXJucyB7U3R5bGV9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZExheWVyOiBmdW5jdGlvbihsYXllciwgYmVmb3JlKSB7XG4gICAgICAgIGlmICh0aGlzLl9sYXllcnNbbGF5ZXIuaWRdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgYWxyZWFkeSBhIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKGxheWVyIGluc3RhbmNlb2YgU3R5bGVMYXllcikpIHtcbiAgICAgICAgICAgIGxheWVyID0gbmV3IFN0eWxlTGF5ZXIobGF5ZXIsIHRoaXMuc3R5bGVzaGVldC5jb25zdGFudHMgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgdGhpcy5fb3JkZXIuc3BsaWNlKGJlZm9yZSA/IHRoaXMuX29yZGVyLmluZGV4T2YoYmVmb3JlKSA6IEluZmluaXR5LCAwLCBsYXllci5pZCk7XG4gICAgICAgIGxheWVyLnJlc29sdmVMYXlvdXQoKTtcbiAgICAgICAgbGF5ZXIucmVzb2x2ZVJlZmVyZW5jZSh0aGlzLl9sYXllcnMpO1xuICAgICAgICBsYXllci5yZXNvbHZlUGFpbnQoKTtcbiAgICAgICAgdGhpcy5fZ3JvdXBMYXllcnMoKTtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuZmlyZSgnbGF5ZXIuYWRkJywge2xheWVyOiBsYXllcn0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgbGF5ZXIgZnJvbSB0aGlzIHN0eWxlc2hlZXQsIGdpdmVuIGl0cyBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGxheWVyIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtTdHlsZX0gdGhpcyBzdHlsZVxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBsYXllciBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XG4gICAgICAgIGlmIChsYXllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fbGF5ZXJzW2ldLnJlZiA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxheWVyKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xuICAgICAgICB0aGlzLl9vcmRlci5zcGxpY2UodGhpcy5fb3JkZXIuaW5kZXhPZihpZCksIDEpO1xuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5maXJlKCdsYXllci5yZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllciBieSBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGRlc2lyZWQgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyB7TGF5ZXJ9IGxheWVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXllcjogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xheWVyc1tpZF07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIElmIGEgbGF5ZXIgaGFzIGEgYHJlZmAgcHJvcGVydHkgdGhhdCBtYWtlcyBpdCBkZXJpdmUgc29tZSB2YWx1ZXNcbiAgICAgKiBmcm9tIGFub3RoZXIgbGF5ZXIsIHJldHVybiB0aGF0IHJlZmVyZW50IGxheWVyLiBPdGhlcndpc2UsXG4gICAgICogcmV0dXJucyB0aGUgbGF5ZXIgaXRzZWxmLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZCB0aGUgbGF5ZXIncyBpZFxuICAgICAqIEByZXR1cm5zIHtMYXllcn0gdGhlIHJlZmVyZW50IGxheWVyIG9yIHRoZSBsYXllciBpdHNlbGZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldFJlZmVyZW50TGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoaWQpO1xuICAgICAgICBpZiAobGF5ZXIucmVmKSB7XG4gICAgICAgICAgICBsYXllciA9IHRoaXMuZ2V0TGF5ZXIobGF5ZXIucmVmKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfSxcblxuICAgIHNldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIsIGZpbHRlcikge1xuICAgICAgICBsYXllciA9IHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcik7XG4gICAgICAgIGxheWVyLmZpbHRlciA9IGZpbHRlcjtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnJlbG9hZCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllcidzIGZpbHRlciBvYmplY3RcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbGF5ZXIgdGhlIGxheWVyIHRvIGluc3BlY3RcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIGxheWVyJ3MgZmlsdGVyLCBpZiBhbnlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZmlsdGVyO1xuICAgIH0sXG5cbiAgICBzZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIGxheWVyID0gdGhpcy5nZXRSZWZlcmVudExheWVyKGxheWVyKTtcbiAgICAgICAgbGF5ZXIuc2V0TGF5b3V0UHJvcGVydHkobmFtZSwgdmFsdWUpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2xheWVyLnNvdXJjZV0ucmVsb2FkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhIGxheW91dCBwcm9wZXJ0eSdzIHZhbHVlIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBsYXllciB0aGUgbGF5ZXIgdG8gaW5zcGVjdFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIHByb3BlcnR5IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZ2V0TGF5b3V0UHJvcGVydHkobmFtZSk7XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSwga2xhc3MpIHtcbiAgICAgICAgdGhpcy5nZXRMYXllcihsYXllcikuc2V0UGFpbnRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihsYXllciwgbmFtZSwga2xhc3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGF5ZXIobGF5ZXIpLmdldFBhaW50UHJvcGVydHkobmFtZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihjb29yZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICAgICAgdmFyIGVycm9yID0gbnVsbDtcblxuICAgICAgICBpZiAocGFyYW1zLmxheWVyKSB7XG4gICAgICAgICAgICBwYXJhbXMubGF5ZXIgPSB7IGlkOiBwYXJhbXMubGF5ZXIgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHV0aWwuYXN5bmNFYWNoKE9iamVjdC5rZXlzKHRoaXMuc291cmNlcyksIGZ1bmN0aW9uKGlkLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgICAgICBzb3VyY2UuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBmdW5jdGlvbihlcnIsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIGZlYXR1cmVzID0gZmVhdHVyZXMuY29uY2F0KHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycikgZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LmJpbmQodGhpcyksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuXG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBmZWF0dXJlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmxheWVyID0gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZlYXR1cmU7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXIucmVtb3ZlKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVTb3VyY2VzOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZXNbaWRdLnVwZGF0ZSh0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9yZWRvUGxhY2VtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXS5yZWRvUGxhY2VtZW50KSB0aGlzLnNvdXJjZXNbaWRdLnJlZG9QbGFjZW1lbnQoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfZm9yd2FyZFNvdXJjZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzb3VyY2U6IGUudGFyZ2V0fSwgZSkpO1xuICAgIH0sXG5cbiAgICBfZm9yd2FyZFRpbGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoZS50eXBlLCB1dGlsLmV4dGVuZCh7c291cmNlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgLy8gQ2FsbGJhY2tzIGZyb20gd2ViIHdvcmtlcnNcblxuICAgICdnZXQgc3ByaXRlIGpzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgeyBzcHJpdGU6IHNwcml0ZS5kYXRhLCByZXRpbmE6IHNwcml0ZS5yZXRpbmEgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7IHNwcml0ZTogc3ByaXRlLmRhdGEsIHJldGluYTogc3ByaXRlLnJldGluYSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgICdnZXQgaWNvbnMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgdmFyIHNwcml0ZUF0bGFzID0gdGhpcy5zcHJpdGVBdGxhcztcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHNwcml0ZSk7XG4gICAgICAgICAgICBzcHJpdGVBdGxhcy5hZGRJY29ucyhwYXJhbXMuaWNvbnMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwcml0ZS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLnNldFNwcml0ZShzcHJpdGUpO1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLmFkZEljb25zKHBhcmFtcy5pY29ucywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2dldCBnbHlwaHMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2x5cGhTb3VyY2UuZ2V0U2ltcGxlR2x5cGhzKHBhcmFtcy5mb250c3RhY2ssIHBhcmFtcy5jb2RlcG9pbnRzLCBwYXJhbXMudWlkLCBjYWxsYmFjayk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmV4cG9ydHMucmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb25zdGFudHMpIHtcbiAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlWzBdID09PSAnQCcgPyBjb25zdGFudHNbdmFsdWVdIDogdmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIGk7XG5cbiAgICB2YWx1ZSA9IHJlc29sdmUodmFsdWUpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtpXSBpbiBjb25zdGFudHMpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtpXSA9IHJlc29sdmUodmFsdWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHZhbHVlID0gdXRpbC5leHRlbmQoe30sIHZhbHVlKTtcbiAgICAgICAgdmFsdWUuc3RvcHMgPSB2YWx1ZS5zdG9wcy5zbGljZSgpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5zdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHZhbHVlLnN0b3BzW2ldWzFdIGluIGNvbnN0YW50cykge1xuICAgICAgICAgICAgICAgIHZhbHVlLnN0b3BzW2ldID0gW1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXVswXSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS5zdG9wc1tpXVsxXSlcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0cy5yZXNvbHZlQWxsID0gZnVuY3Rpb24gKHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIGlmICghY29uc3RhbnRzKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcblxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIGZvciAodmFyIGtleSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gZXhwb3J0cy5yZXNvbHZlKHByb3BlcnRpZXNba2V5XSwgY29uc3RhbnRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhcnNlQ1NTQ29sb3IgPSByZXF1aXJlKCdjc3Njb2xvcnBhcnNlcicpLnBhcnNlQ1NTQ29sb3I7XG52YXIgbWFwYm94R0xGdW5jdGlvbiA9IHJlcXVpcmUoJ21hcGJveC1nbC1mdW5jdGlvbicpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZURlY2xhcmF0aW9uO1xuXG5mdW5jdGlvbiBTdHlsZURlY2xhcmF0aW9uKHJlZmVyZW5jZSwgdmFsdWUpIHtcbiAgICB0aGlzLnR5cGUgPSByZWZlcmVuY2UudHlwZTtcbiAgICB0aGlzLnRyYW5zaXRpb25hYmxlID0gcmVmZXJlbmNlLnRyYW5zaXRpb247XG5cbiAgICAvLyBpbW11dGFibGUgcmVwcmVzZW50YXRpb24gb2YgdmFsdWUuIHVzZWQgZm9yIGNvbXBhcmlzb25cbiAgICB0aGlzLmpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbiAgICBpZiAodGhpcy50eXBlICE9PSAnY29sb3InKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBwcmVwYXJlQ29sb3JGdW5jdGlvbih2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHBhcnNlQ29sb3IodmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChyZWZlcmVuY2UuZnVuY3Rpb24gPT09ICdpbnRlcnBvbGF0ZWQnKSB7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlID0gbWFwYm94R0xGdW5jdGlvbi5pbnRlcnBvbGF0ZWQodGhpcy52YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jYWxjdWxhdGUgPSBtYXBib3hHTEZ1bmN0aW9uWydwaWVjZXdpc2UtY29uc3RhbnQnXSh0aGlzLnZhbHVlKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZS50cmFuc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZSA9IHRyYW5zaXRpb25lZCh0aGlzLmNhbGN1bGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb25lZChjYWxjdWxhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeiwgemgsIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBmcmFjdGlvbiA9IHogJSAxO1xuICAgICAgICB2YXIgdCA9IE1hdGgubWluKChEYXRlLm5vdygpIC0gemgubGFzdEludGVnZXJab29tVGltZSkgLyBkdXJhdGlvbiwgMSk7XG4gICAgICAgIHZhciBmcm9tU2NhbGUgPSAxO1xuICAgICAgICB2YXIgdG9TY2FsZSA9IDE7XG4gICAgICAgIHZhciBtaXgsIGZyb20sIHRvO1xuXG4gICAgICAgIGlmICh6ID4gemgubGFzdEludGVnZXJab29tKSB7XG4gICAgICAgICAgICBtaXggPSBmcmFjdGlvbiArICgxIC0gZnJhY3Rpb24pICogdDtcbiAgICAgICAgICAgIGZyb21TY2FsZSAqPSAyO1xuICAgICAgICAgICAgZnJvbSA9IGNhbGN1bGF0ZSh6IC0gMSk7XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1peCA9IDEgLSAoMSAtIHQpICogZnJhY3Rpb247XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgICAgIGZyb20gPSBjYWxjdWxhdGUoeiArIDEpO1xuICAgICAgICAgICAgZnJvbVNjYWxlIC89IDI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgIGZyb21TY2FsZTogZnJvbVNjYWxlLFxuICAgICAgICAgICAgdG86IHRvLFxuICAgICAgICAgICAgdG9TY2FsZTogdG9TY2FsZSxcbiAgICAgICAgICAgIHQ6IG1peFxuICAgICAgICB9O1xuICAgIH07XG59XG5cbnZhciBjb2xvckNhY2hlID0ge307XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3IodmFsdWUpIHtcbiAgICBpZiAoY29sb3JDYWNoZVt2YWx1ZV0pIHJldHVybiBjb2xvckNhY2hlW3ZhbHVlXTtcbiAgICB2YXIgY29sb3IgPSBwcmVwYXJlQ29sb3IocGFyc2VDU1NDb2xvcih2YWx1ZSkpO1xuICAgIGNvbG9yQ2FjaGVbdmFsdWVdID0gY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3IoYykge1xuICAgIHJldHVybiBbY1swXSAvIDI1NSwgY1sxXSAvIDI1NSwgY1syXSAvIDI1NSwgY1szXSAvIDFdO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3JGdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIHV0aWwuZXh0ZW5kKHt9LCBmLCB7c3RvcHM6IGYuc3RvcHMubWFwKGZ1bmN0aW9uKHN0b3ApIHtcbiAgICAgICAgcmV0dXJuIFtzdG9wWzBdLCBwYXJzZUNvbG9yKHN0b3BbMV0pXTtcbiAgICB9KX0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbicpO1xuXG52YXIgbG9va3VwID0ge1xuICAgIHBhaW50OiB7fSxcbiAgICBsYXlvdXQ6IHt9XG59O1xuXG5yZWZlcmVuY2UubGF5ZXIudHlwZS52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih0eXBlKSB7XG4gICAgbG9va3VwLnBhaW50W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsncGFpbnRfJyArIHR5cGVdKTtcbiAgICBsb29rdXAubGF5b3V0W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsnbGF5b3V0XycgKyB0eXBlXSk7XG59KTtcblxuZnVuY3Rpb24gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZSkge1xuICAgIGZ1bmN0aW9uIFN0eWxlRGVjbGFyYXRpb25TZXQocHJvcGVydGllcywgY29uc3RhbnRzKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IHt9O1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9ucyA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2NvbnN0YW50cyA9IGNvbnN0YW50cztcblxuICAgICAgICBmb3IgKHZhciBrIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXNba10gPSBTdHlsZUNvbnN0YW50LnJlc29sdmUocHJvcGVydGllc1trXSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKHJlZmVyZW5jZSkuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgICAgIHZhciBwcm9wZXJ0eSA9IHJlZmVyZW5jZVtrXTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3R5bGVEZWNsYXJhdGlvblNldC5wcm90b3R5cGUsIGssIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlc1trXSA9IG5ldyBTdHlsZURlY2xhcmF0aW9uKHByb3BlcnR5LCBTdHlsZUNvbnN0YW50LnJlc29sdmUodiwgdGhpcy5fY29uc3RhbnRzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzW2tdLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocHJvcGVydHkudHJhbnNpdGlvbikge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLCBrICsgJy10cmFuc2l0aW9uJywge1xuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2l0aW9uc1trXSA9IHY7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNpdGlvbnNba107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xuICAgIH07XG5cbiAgICBTdHlsZURlY2xhcmF0aW9uU2V0LnByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24oaywgZ2xvYmFsKSB7XG4gICAgICAgIHZhciB0ID0gdGhpcy5fdHJhbnNpdGlvbnNba10gfHwge307XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogdXRpbC5jb2FsZXNjZSh0LmR1cmF0aW9uLCBnbG9iYWwuZHVyYXRpb24sIDMwMCksXG4gICAgICAgICAgICBkZWxheTogdXRpbC5jb2FsZXNjZSh0LmRlbGF5LCBnbG9iYWwuZGVsYXksIDApXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgIGZvciAodmFyIHYgaW4gdGhpcy5fdmFsdWVzKSB7XG4gICAgICAgICAgICByZXN1bHRbdl0gPSB0aGlzLl92YWx1ZXNbdl0udmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMuX3RyYW5zaXRpb25zKSB7XG4gICAgICAgICAgICByZXN1bHRbdCArICctdHJhbnNpdGlvbiddID0gdGhpcy5fdHJhbnNpdGlvbnNbdl07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICByZXR1cm4gU3R5bGVEZWNsYXJhdGlvblNldDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihyZW5kZXJUeXBlLCBsYXllclR5cGUsIHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIHJldHVybiBuZXcgbG9va3VwW3JlbmRlclR5cGVdW2xheWVyVHlwZV0ocHJvcGVydGllcywgY29uc3RhbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZVRyYW5zaXRpb24gPSByZXF1aXJlKCcuL3N0eWxlX3RyYW5zaXRpb24nKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uU2V0ID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbl9zZXQnKTtcbnZhciBMYXlvdXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9sYXlvdXRfcHJvcGVydGllcycpO1xudmFyIFBhaW50UHJvcGVydGllcyA9IHJlcXVpcmUoJy4vcGFpbnRfcHJvcGVydGllcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFN0eWxlTGF5ZXIobGF5ZXIsIGNvbnN0YW50cykge1xuICAgIHRoaXMuX2xheWVyID0gbGF5ZXI7XG4gICAgdGhpcy5fY29uc3RhbnRzID0gY29uc3RhbnRzO1xuXG4gICAgdGhpcy5pZCA9IGxheWVyLmlkO1xuICAgIHRoaXMucmVmID0gbGF5ZXIucmVmO1xuXG4gICAgLy8gUmVzb2x2ZWQgYW5kIGNhc2NhZGVkIHBhaW50IHByb3BlcnRpZXMuXG4gICAgdGhpcy5fcmVzb2x2ZWQgPSB7fTsgLy8gY2xhc3MgbmFtZSAtPiBTdHlsZURlY2xhcmF0aW9uU2V0XG4gICAgdGhpcy5fY2FzY2FkZWQgPSB7fTsgLy8gcHJvcGVydHkgbmFtZSAtPiBTdHlsZVRyYW5zaXRpb25cblxuICAgIHRoaXMuYXNzaWduKGxheWVyKTtcbn1cblxuU3R5bGVMYXllci5wcm90b3R5cGUgPSB7XG4gICAgcmVzb2x2ZUxheW91dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5yZWYpIHtcbiAgICAgICAgICAgIHRoaXMubGF5b3V0ID0gbmV3IExheW91dFByb3BlcnRpZXNbdGhpcy50eXBlXShcbiAgICAgICAgICAgICAgICBTdHlsZUNvbnN0YW50LnJlc29sdmVBbGwodGhpcy5fbGF5ZXIubGF5b3V0LCB0aGlzLl9jb25zdGFudHMpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMubGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5sYXlvdXQuaGFzT3duUHJvcGVydHkoJ3RleHQtcm90YXRpb24tYWxpZ25tZW50JykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPSAnbWFwJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxheW91dC5oYXNPd25Qcm9wZXJ0eSgnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnc3ltYm9sLWF2b2lkLWVkZ2VzJ10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldExheW91dFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmxheW91dFtuYW1lXSA9IFN0eWxlQ29uc3RhbnQucmVzb2x2ZSh2YWx1ZSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICB9LFxuXG4gICAgZ2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGF5b3V0W25hbWVdO1xuICAgIH0sXG5cbiAgICByZXNvbHZlUmVmZXJlbmNlOiBmdW5jdGlvbihsYXllcnMpIHtcbiAgICAgICAgaWYgKHRoaXMucmVmKSB7XG4gICAgICAgICAgICB0aGlzLmFzc2lnbihsYXllcnNbdGhpcy5yZWZdKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZXNvbHZlUGFpbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBwIGluIHRoaXMuX2xheWVyKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBwLm1hdGNoKC9ecGFpbnQoPzpcXC4oLiopKT8kLyk7XG4gICAgICAgICAgICBpZiAoIW1hdGNoKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZWRbbWF0Y2hbMV0gfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHRoaXMuX2xheWVyW3BdLCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucykge1xuICAgICAgICAgICAgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHt9LCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgICAgIGRlY2xhcmF0aW9uc1tuYW1lXSA9IHZhbHVlO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucylcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBkZWNsYXJhdGlvbnNbbmFtZV07XG4gICAgfSxcblxuICAgIGNhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMsIGdsb2JhbFRyYW5zLCBhbmltYXRpb25Mb29wKSB7XG4gICAgICAgIGZvciAodmFyIGtsYXNzIGluIHRoaXMuX3Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpZiAoa2xhc3MgIT09IFwiXCIgJiYgIWNsYXNzZXNba2xhc3NdKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3NdLFxuICAgICAgICAgICAgICAgIHZhbHVlcyA9IGRlY2xhcmF0aW9ucy52YWx1ZXMoKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgayBpbiB2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RGVjbGFyYXRpb24gPSB2YWx1ZXNba107XG4gICAgICAgICAgICAgICAgdmFyIG9sZFRyYW5zaXRpb24gPSBvcHRpb25zLnRyYW5zaXRpb24gPyB0aGlzLl9jYXNjYWRlZFtrXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IHRyYW5zaXRpb24gaWYgdGhlIGRlY2xhcmF0aW9uIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpZiAoIW9sZFRyYW5zaXRpb24gfHwgb2xkVHJhbnNpdGlvbi5kZWNsYXJhdGlvbi5qc29uICE9PSBuZXdEZWNsYXJhdGlvbi5qc29uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdTdHlsZVRyYW5zID0gZGVjbGFyYXRpb25zLnRyYW5zaXRpb24oaywgZ2xvYmFsVHJhbnMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMuX2Nhc2NhZGVkW2tdID1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTdHlsZVRyYW5zaXRpb24obmV3RGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIG5ld1N0eWxlVHJhbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJ1biB0aGUgYW5pbWF0aW9uIGxvb3AgdW50aWwgdGhlIGVuZCBvZiB0aGUgdHJhbnNpdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld1RyYW5zaXRpb24uaW5zdGFudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdUcmFuc2l0aW9uLmxvb3BJRCA9IGFuaW1hdGlvbkxvb3Auc2V0KG5ld1RyYW5zaXRpb24uZW5kVGltZSAtIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkxvb3AuY2FuY2VsKG9sZFRyYW5zaXRpb24ubG9vcElEKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZWNhbGN1bGF0ZTogZnVuY3Rpb24oeiwgem9vbUhpc3RvcnkpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLnR5cGUsXG4gICAgICAgICAgICBjYWxjdWxhdGVkID0gdGhpcy5wYWludCA9IG5ldyBQYWludFByb3BlcnRpZXNbdHlwZV0oKTtcblxuICAgICAgICBmb3IgKHZhciBrIGluIHRoaXMuX2Nhc2NhZGVkKSB7XG4gICAgICAgICAgICBjYWxjdWxhdGVkW2tdID0gdGhpcy5fY2FzY2FkZWRba10uYXQoeiwgem9vbUhpc3RvcnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRkZW4gPSAodGhpcy5taW56b29tICYmIHogPCB0aGlzLm1pbnpvb20pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHRoaXMubWF4em9vbSAmJiB6ID49IHRoaXMubWF4em9vbSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpbmNsdWRlIHZpc2liaWxpdHkgY2hlY2sgZm9yIG5vbi1idWNrZXRlZCBiYWNrZ3JvdW5kIGxheWVyc1xuICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmxheW91dC52aXNpYmlsaXR5ID09PSAnbm9uZScpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgaWYgKChjYWxjdWxhdGVkWyd0ZXh0LW9wYWNpdHknXSA9PT0gMCB8fCAhdGhpcy5sYXlvdXRbJ3RleHQtZmllbGQnXSkgJiZcbiAgICAgICAgICAgICAgICAoY2FsY3VsYXRlZFsnaWNvbi1vcGFjaXR5J10gPT09IDAgfHwgIXRoaXMubGF5b3V0WydpY29uLWltYWdlJ10pKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVtdWx0aXBseUxheWVyKGNhbGN1bGF0ZWQsICd0ZXh0Jyk7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihjYWxjdWxhdGVkLCAnaWNvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY2FsY3VsYXRlZFt0eXBlICsgJy1vcGFjaXR5J10gPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZW11bHRpcGx5TGF5ZXIoY2FsY3VsYXRlZCwgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY2FzY2FkZWRbJ2xpbmUtZGFzaGFycmF5J10pIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBsaW5lIGlzIGRhc2hlZCwgc2NhbGUgdGhlIGRhc2ggbGVuZ3RocyBieSB0aGUgbGluZVxuICAgICAgICAgICAgLy8gd2lkdGggYXQgdGhlIHByZXZpb3VzIHJvdW5kIHpvb20gbGV2ZWwuXG4gICAgICAgICAgICB2YXIgZGFzaEFycmF5ID0gY2FsY3VsYXRlZFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICAgICAgICAgIHZhciBsaW5lV2lkdGggPSB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddID9cbiAgICAgICAgICAgICAgICB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddLmF0KE1hdGguZmxvb3IoeiksIEluZmluaXR5KSA6XG4gICAgICAgICAgICAgICAgY2FsY3VsYXRlZFsnbGluZS13aWR0aCddO1xuXG4gICAgICAgICAgICBkYXNoQXJyYXkuZnJvbVNjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgICAgIGRhc2hBcnJheS50b1NjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfSxcblxuICAgIGFzc2lnbjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKGxheWVyLFxuICAgICAgICAgICAgWyd0eXBlJywgJ3NvdXJjZScsICdzb3VyY2UtbGF5ZXInLFxuICAgICAgICAgICAgJ21pbnpvb20nLCAnbWF4em9vbScsICdmaWx0ZXInLFxuICAgICAgICAgICAgJ2xheW91dCddKSk7XG4gICAgfSxcblxuICAgIGpzb246IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdXRpbC5leHRlbmQoe30sXG4gICAgICAgICAgICB0aGlzLl9sYXllcixcbiAgICAgICAgICAgIHV0aWwucGljayh0aGlzLFxuICAgICAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJyxcbiAgICAgICAgICAgICAgICAnbWluem9vbScsICdtYXh6b29tJywgJ2ZpbHRlcicsXG4gICAgICAgICAgICAgICAgJ2xheW91dCcsICdwYWludCddKSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcHJlbXVsdGlwbHlMYXllcihsYXllciwgdHlwZSkge1xuICAgIHZhciBjb2xvclByb3AgPSB0eXBlICsgJy1jb2xvcicsXG4gICAgICAgIGhhbG9Qcm9wID0gdHlwZSArICctaGFsby1jb2xvcicsXG4gICAgICAgIG91dGxpbmVQcm9wID0gdHlwZSArICctb3V0bGluZS1jb2xvcicsXG4gICAgICAgIGNvbG9yID0gbGF5ZXJbY29sb3JQcm9wXSxcbiAgICAgICAgaGFsb0NvbG9yID0gbGF5ZXJbaGFsb1Byb3BdLFxuICAgICAgICBvdXRsaW5lQ29sb3IgPSBsYXllcltvdXRsaW5lUHJvcF0sXG4gICAgICAgIG9wYWNpdHkgPSBsYXllclt0eXBlICsgJy1vcGFjaXR5J107XG5cbiAgICB2YXIgY29sb3JPcGFjaXR5ID0gY29sb3IgJiYgKG9wYWNpdHkgKiBjb2xvclszXSk7XG4gICAgdmFyIGhhbG9PcGFjaXR5ID0gaGFsb0NvbG9yICYmIChvcGFjaXR5ICogaGFsb0NvbG9yWzNdKTtcbiAgICB2YXIgb3V0bGluZU9wYWNpdHkgPSBvdXRsaW5lQ29sb3IgJiYgKG9wYWNpdHkgKiBvdXRsaW5lQ29sb3JbM10pO1xuXG4gICAgaWYgKGNvbG9yT3BhY2l0eSAhPT0gdW5kZWZpbmVkICYmIGNvbG9yT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbY29sb3JQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW2NvbG9yWzBdLCBjb2xvclsxXSwgY29sb3JbMl0sIGNvbG9yT3BhY2l0eV0pO1xuICAgIH1cbiAgICBpZiAoaGFsb09wYWNpdHkgIT09IHVuZGVmaW5lZCAmJiBoYWxvT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbaGFsb1Byb3BdID0gdXRpbC5wcmVtdWx0aXBseShbaGFsb0NvbG9yWzBdLCBoYWxvQ29sb3JbMV0sIGhhbG9Db2xvclsyXSwgaGFsb09wYWNpdHldKTtcbiAgICB9XG4gICAgaWYgKG91dGxpbmVPcGFjaXR5ICE9PSB1bmRlZmluZWQgJiYgb3V0bGluZU9wYWNpdHkgPCAxKSB7XG4gICAgICAgIGxheWVyW291dGxpbmVQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW291dGxpbmVDb2xvclswXSwgb3V0bGluZUNvbG9yWzFdLCBvdXRsaW5lQ29sb3JbMl0sIG91dGxpbmVPcGFjaXR5XSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlVHJhbnNpdGlvbjtcblxuLypcbiAqIFJlcHJlc2VudHMgYSB0cmFuc2l0aW9uIGJldHdlZW4gdHdvIGRlY2xhcmF0aW9uc1xuICovXG5mdW5jdGlvbiBTdHlsZVRyYW5zaXRpb24oZGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIHZhbHVlKSB7XG5cbiAgICB0aGlzLmRlY2xhcmF0aW9uID0gZGVjbGFyYXRpb247XG4gICAgdGhpcy5zdGFydFRpbWUgPSB0aGlzLmVuZFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgdmFyIHR5cGUgPSBkZWNsYXJhdGlvbi50eXBlO1xuICAgIGlmICgodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ2FycmF5JykgJiYgZGVjbGFyYXRpb24udHJhbnNpdGlvbmFibGUpIHtcbiAgICAgICAgdGhpcy5pbnRlcnAgPSBpbnRlcnBab29tVHJhbnNpdGlvbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW50ZXJwID0gaW50ZXJwb2xhdGVbdHlwZV07XG4gICAgfVxuXG4gICAgdGhpcy5vbGRUcmFuc2l0aW9uID0gb2xkVHJhbnNpdGlvbjtcbiAgICB0aGlzLmR1cmF0aW9uID0gdmFsdWUuZHVyYXRpb24gfHwgMDtcbiAgICB0aGlzLmRlbGF5ID0gdmFsdWUuZGVsYXkgfHwgMDtcblxuICAgIGlmICghdGhpcy5pbnN0YW50KCkpIHtcbiAgICAgICAgdGhpcy5lbmRUaW1lID0gdGhpcy5zdGFydFRpbWUgKyB0aGlzLmR1cmF0aW9uICsgdGhpcy5kZWxheTtcbiAgICAgICAgdGhpcy5lYXNlID0gdXRpbC5lYXNlQ3ViaWNJbk91dDtcbiAgICB9XG5cbiAgICBpZiAob2xkVHJhbnNpdGlvbiAmJiBvbGRUcmFuc2l0aW9uLmVuZFRpbWUgPD0gdGhpcy5zdGFydFRpbWUpIHtcbiAgICAgICAgLy8gT2xkIHRyYW5zaXRpb24gaXMgZG9uZSBydW5uaW5nLCBzbyB3ZSBjYW5cbiAgICAgICAgLy8gZGVsZXRlIGl0cyByZWZlcmVuY2UgdG8gaXRzIG9sZCB0cmFuc2l0aW9uLlxuXG4gICAgICAgIGRlbGV0ZSBvbGRUcmFuc2l0aW9uLm9sZFRyYW5zaXRpb247XG4gICAgfVxufVxuXG5TdHlsZVRyYW5zaXRpb24ucHJvdG90eXBlLmluc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMub2xkVHJhbnNpdGlvbiB8fCAhdGhpcy5pbnRlcnAgfHwgKHRoaXMuZHVyYXRpb24gPT09IDAgJiYgdGhpcy5kZWxheSA9PT0gMCk7XG59O1xuXG4vKlxuICogUmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgdHJhbnNpdGlvbmluZyBwcm9wZXJ0eSBhdCB6b29tIGxldmVsIGB6YCBhbmQgb3B0aW9uYWwgdGltZSBgdGBcbiAqL1xuU3R5bGVUcmFuc2l0aW9uLnByb3RvdHlwZS5hdCA9IGZ1bmN0aW9uKHosIHpvb21IaXN0b3J5LCB0KSB7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLmRlY2xhcmF0aW9uLmNhbGN1bGF0ZSh6LCB6b29tSGlzdG9yeSwgdGhpcy5kdXJhdGlvbik7XG5cbiAgICBpZiAodGhpcy5pbnN0YW50KCkpIHJldHVybiB2YWx1ZTtcblxuICAgIHQgPSB0IHx8IERhdGUubm93KCk7XG5cbiAgICBpZiAodCA8IHRoaXMuZW5kVGltZSkge1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm9sZFRyYW5zaXRpb24uYXQoeiwgem9vbUhpc3RvcnksIHRoaXMuc3RhcnRUaW1lKTtcbiAgICAgICAgdmFyIGVhc2VkID0gdGhpcy5lYXNlKCh0IC0gdGhpcy5zdGFydFRpbWUgLSB0aGlzLmRlbGF5KSAvIHRoaXMuZHVyYXRpb24pO1xuICAgICAgICB2YWx1ZSA9IHRoaXMuaW50ZXJwKG9sZFZhbHVlLCB2YWx1ZSwgZWFzZWQpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcblxufTtcblxuZnVuY3Rpb24gaW50ZXJwWm9vbVRyYW5zaXRpb25lZChmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGZyb20udG8sXG4gICAgICAgIGZyb21TY2FsZTogZnJvbS50b1NjYWxlLFxuICAgICAgICB0bzogdG8udG8sXG4gICAgICAgIHRvU2NhbGU6IHRvLnRvU2NhbGUsXG4gICAgICAgIHQ6IHRcbiAgICB9O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuY2hvcjtcblxuZnVuY3Rpb24gQW5jaG9yKHgsIHksIGFuZ2xlLCBzZWdtZW50KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcblxuICAgIGlmIChzZWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDtcbiAgICB9XG59XG5cbkFuY2hvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBvaW50LnByb3RvdHlwZSk7XG5cbkFuY2hvci5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IEFuY2hvcih0aGlzLngsIHRoaXMueSwgdGhpcy5hbmdsZSwgdGhpcy5zZWdtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQmluUGFjaztcbmZ1bmN0aW9uIEJpblBhY2sod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLmZyZWUgPSBbeyB4OiAwLCB5OiAwLCB3OiB3aWR0aCwgaDogaGVpZ2h0IH1dO1xufVxuXG4vKipcbiAqIFNpbXBsZSBhbGdvcml0aG0gdG8gcmVjdXJzaXZlbHkgbWVyZ2UgdGhlIG5ld2x5IHJlbGVhc2VkIGNlbGwgd2l0aCBpdHNcbiAqIG5laWdoYm9yLiBUaGlzIGRvZXNuJ3QgbWVyZ2UgbW9yZSB0aGFuIHR3byBjZWxscyBhdCBhIHRpbWUsIGFuZCBmYWlsc1xuICogZm9yIGNvbXBsaWNhdGVkIG1lcmdlcy5cbiAqIEBwcml2YXRlXG4gKi9cbkJpblBhY2sucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbihyZWN0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmZyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmZyZWVbaV07XG5cbiAgICAgICAgaWYgKGZyZWUueSA9PT0gcmVjdC55ICYmIGZyZWUuaCA9PT0gcmVjdC5oICYmIGZyZWUueCArIGZyZWUudyA9PT0gcmVjdC54KSB7XG4gICAgICAgICAgICBmcmVlLncgKz0gcmVjdC53O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZnJlZS54ID09PSByZWN0LnggJiYgZnJlZS53ID09PSByZWN0LncgJiYgZnJlZS55ICsgZnJlZS5oID09PSByZWN0LnkpIHtcbiAgICAgICAgICAgIGZyZWUuaCArPSByZWN0Lmg7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWN0LnkgPT09IGZyZWUueSAmJiByZWN0LmggPT09IGZyZWUuaCAmJiByZWN0LnggKyByZWN0LncgPT09IGZyZWUueCkge1xuICAgICAgICAgICAgZnJlZS54ID0gcmVjdC54O1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcblxuICAgICAgICB9IGVsc2UgaWYgKHJlY3QueCA9PT0gZnJlZS54ICYmIHJlY3QudyA9PT0gZnJlZS53ICYmIHJlY3QueSArIHJlY3QuaCA9PT0gZnJlZS55KSB7XG4gICAgICAgICAgICBmcmVlLnkgPSByZWN0Lnk7XG4gICAgICAgICAgICBmcmVlLmggKz0gcmVjdC5oO1xuXG4gICAgICAgIH0gZWxzZSBjb250aW51ZTtcblxuICAgICAgICB0aGlzLmZyZWUuc3BsaWNlKGksIDEpO1xuICAgICAgICB0aGlzLnJlbGVhc2UoZnJlZSk7XG4gICAgICAgIHJldHVybjtcblxuICAgIH1cbiAgICB0aGlzLmZyZWUucHVzaChyZWN0KTtcbn07XG5cbkJpblBhY2sucHJvdG90eXBlLmFsbG9jYXRlID0gZnVuY3Rpb24od2lkdGgsIGhlaWdodCkge1xuICAgIC8vIEZpbmQgdGhlIHNtYWxsZXN0IGZyZWUgcmVjdCBhbmdsZVxuICAgIHZhciByZWN0ID0geyB4OiBJbmZpbml0eSwgeTogSW5maW5pdHksIHc6IEluZmluaXR5LCBoOiBJbmZpbml0eSB9O1xuICAgIHZhciBzbWFsbGVzdCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZWYgPSB0aGlzLmZyZWVbaV07XG4gICAgICAgIGlmICh3aWR0aCA8PSByZWYudyAmJiBoZWlnaHQgPD0gcmVmLmggJiYgcmVmLnkgPD0gcmVjdC55ICYmIHJlZi54IDw9IHJlY3QueCkge1xuICAgICAgICAgICAgcmVjdCA9IHJlZjtcbiAgICAgICAgICAgIHNtYWxsZXN0ID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzbWFsbGVzdCA8IDApIHtcbiAgICAgICAgLy8gVGhlcmUncyBubyBzcGFjZSBsZWZ0IGZvciB0aGlzIGNoYXIuXG4gICAgICAgIHJldHVybiB7IHg6IC0xLCB5OiAtMSB9O1xuICAgIH1cblxuICAgIHRoaXMuZnJlZS5zcGxpY2Uoc21hbGxlc3QsIDEpO1xuXG4gICAgLy8gU2hvcnRlci9Mb25nZXIgQXhpcyBTcGxpdCBSdWxlIChTQVMpXG4gICAgLy8gaHR0cDovL2NsYi5kZW1vbi5maS9maWxlcy9SZWN0YW5nbGVCaW5QYWNrLnBkZiBwLiAxNVxuICAgIC8vIElnbm9yZSB0aGUgZGltZW5zaW9uIG9mIFIgYW5kIGp1c3Qgc3BsaXQgbG9uZyB0aGUgc2hvcnRlciBkaW1lbnNpb25cbiAgICAvLyBTZWUgQWxzbzogaHR0cDovL3d3dy5jcy5wcmluY2V0b24uZWR1L35jaGF6ZWxsZS9wdWJzL2JsYmlucGFja2luZy5wZGZcbiAgICBpZiAocmVjdC53IDwgcmVjdC5oKSB7XG4gICAgICAgIC8vIHNwbGl0IGhvcml6b250YWxseVxuICAgICAgICAvLyArLS0rLS0tK1xuICAgICAgICAvLyB8X198X19ffCAgPC0tIGIxXG4gICAgICAgIC8vICstLS0tLS0rICA8LS0gYjJcbiAgICAgICAgaWYgKHJlY3QudyA+IHdpZHRoKSB0aGlzLmZyZWUucHVzaCh7IHg6IHJlY3QueCArIHdpZHRoLCB5OiByZWN0LnksIHc6IHJlY3QudyAtIHdpZHRoLCBoOiBoZWlnaHQgfSk7XG4gICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHJlY3QudywgaDogcmVjdC5oIC0gaGVpZ2h0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNwbGl0IHZlcnRpY2FsbHlcbiAgICAgICAgLy8gKy0tKy0tLStcbiAgICAgICAgLy8gfF9ffCAgIHwgPC0tIGIxXG4gICAgICAgIC8vICstLXwtLS0rIDwtLSBiMlxuICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IHJlY3QuaCB9KTtcbiAgICAgICAgaWYgKHJlY3QuaCA+IGhlaWdodCkgdGhpcy5mcmVlLnB1c2goeyB4OiByZWN0LngsIHk6IHJlY3QueSArIGhlaWdodCwgdzogd2lkdGgsIGg6IHJlY3QuaCAtIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB4OiByZWN0LngsIHk6IHJlY3QueSwgdzogd2lkdGgsIGg6IGhlaWdodCB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjaGVja01heEFuZ2xlO1xuXG5mdW5jdGlvbiBjaGVja01heEFuZ2xlKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIHdpbmRvd1NpemUsIG1heEFuZ2xlKSB7XG5cbiAgICAvLyBob3Jpem9udGFsIGxhYmVscyBhbHdheXMgcGFzc1xuICAgIGlmIChhbmNob3Iuc2VnbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBwID0gYW5jaG9yO1xuICAgIHZhciBpbmRleCA9IGFuY2hvci5zZWdtZW50ICsgMTtcbiAgICB2YXIgYW5jaG9yRGlzdGFuY2UgPSAwO1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPiAtbGFiZWxMZW5ndGggLyAyKSB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIGlmIChpbmRleCA8IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICBhbmNob3JEaXN0YW5jZSAtPSBsaW5lW2luZGV4XS5kaXN0KHApO1xuICAgICAgICBwID0gbGluZVtpbmRleF07XG4gICAgfVxuXG4gICAgYW5jaG9yRGlzdGFuY2UgKz0gbGluZVtpbmRleF0uZGlzdChsaW5lW2luZGV4ICsgMV0pO1xuICAgIGluZGV4Kys7XG5cbiAgICAvLyBzdG9yZSByZWNlbnQgY29ybmVycyBhbmQgdGhlaXIgdG90YWwgYW5nbGUgZGlmZmVyZW5jZVxuICAgIHZhciByZWNlbnRDb3JuZXJzID0gW107XG4gICAgdmFyIHJlY2VudEFuZ2xlRGVsdGEgPSAwO1xuXG4gICAgLy8gbW92ZSBmb3J3YXJkcyBieSB0aGUgbGVuZ3RoIG9mIHRoZSBsYWJlbCBhbmQgY2hlY2sgYW5nbGVzIGFsb25nIHRoZSB3YXlcbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPCBsYWJlbExlbmd0aCAvIDIpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2luZGV4IC0gMV07XG4gICAgICAgIHZhciBjdXJyZW50ID0gbGluZVtpbmRleF07XG4gICAgICAgIHZhciBuZXh0ID0gbGluZVtpbmRleCArIDFdO1xuXG4gICAgICAgIC8vIHRoZXJlIGlzbid0IGVub3VnaCByb29tIGZvciB0aGUgbGFiZWwgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGxpbmVcbiAgICAgICAgaWYgKCFuZXh0KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIGFuZ2xlRGVsdGEgPSBwcmV2LmFuZ2xlVG8oY3VycmVudCkgLSBjdXJyZW50LmFuZ2xlVG8obmV4dCk7XG4gICAgICAgIC8vIHJlc3RyaWN0IGFuZ2xlIHRvIC1waS4ucGkgcmFuZ2VcbiAgICAgICAgYW5nbGVEZWx0YSA9ICgoYW5nbGVEZWx0YSArIDMgKiBNYXRoLlBJKSAlIChNYXRoLlBJICogMikpIC0gTWF0aC5QSTtcblxuICAgICAgICByZWNlbnRDb3JuZXJzLnB1c2goe1xuICAgICAgICAgICAgZGlzdGFuY2U6IGFuY2hvckRpc3RhbmNlLFxuICAgICAgICAgICAgYW5nbGVEZWx0YTogYW5nbGVEZWx0YVxuICAgICAgICB9KTtcbiAgICAgICAgcmVjZW50QW5nbGVEZWx0YSArPSBhbmdsZURlbHRhO1xuXG4gICAgICAgIC8vIHJlbW92ZSBjb3JuZXJzIHRoYXQgYXJlIGZhciBlbm91Z2ggYXdheSBmcm9tIHRoZSBsaXN0IG9mIHJlY2VudCBhbmNob3JzXG4gICAgICAgIHdoaWxlIChhbmNob3JEaXN0YW5jZSAtIHJlY2VudENvcm5lcnNbMF0uZGlzdGFuY2UgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICByZWNlbnRBbmdsZURlbHRhIC09IHJlY2VudENvcm5lcnMuc2hpZnQoKS5hbmdsZURlbHRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHN1bSBvZiBhbmdsZXMgd2l0aGluIHRoZSB3aW5kb3cgYXJlYSBleGNlZWRzIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuIGNoZWNrIGZhaWxzLlxuICAgICAgICBpZiAoTWF0aC5hYnMocmVjZW50QW5nbGVEZWx0YSkgPiBtYXhBbmdsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGluZGV4Kys7XG4gICAgICAgIGFuY2hvckRpc3RhbmNlICs9IGN1cnJlbnQuZGlzdChuZXh0KTtcbiAgICB9XG5cbiAgICAvLyBubyBwYXJ0IG9mIHRoZSBsaW5lIGhhZCBhbiBhbmdsZSBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gYWxsb3dlZC4gY2hlY2sgcGFzc2VzLlxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsaXBMaW5lO1xuXG5mdW5jdGlvbiBjbGlwTGluZShsaW5lcywgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgY2xpcHBlZExpbmVzID0gW107XG5cbiAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxpbmVzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgIHZhciBsaW5lID0gbGluZXNbbF07XG4gICAgICAgIHZhciBjbGlwcGVkTGluZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcDAgPSBsaW5lW2ldO1xuICAgICAgICAgICAgdmFyIHAxID0gbGluZVtpICsgMV07XG5cblxuICAgICAgICAgICAgaWYgKHAwLnggPCB4MSAmJiBwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueCA8IHgxKSB7XG4gICAgICAgICAgICAgICAgcDAgPSBuZXcgUG9pbnQoeDEsIHAwLnkgKyAocDEueSAtIHAwLnkpICogKCh4MSAtIHAwLngpIC8gKHAxLnggLSBwMC54KSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MSwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgxIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55IDwgeTEgJiYgcDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnkgPCB5MSkge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MSAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgcDEgPSBuZXcgUG9pbnQocDAueCArIChwMS54IC0gcDAueCkgKiAoKHkxIC0gcDAueSkgLyAocDEueSAtIHAwLnkpKSwgeTEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocDAueCA+PSB4MiAmJiBwMS54ID49IHgyKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMCA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAxLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55ID49IHkyICYmIHAxLnkgPj0geTIpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAxID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFjbGlwcGVkTGluZSB8fCAhcDAuZXF1YWxzKGNsaXBwZWRMaW5lW2NsaXBwZWRMaW5lLmxlbmd0aCAtIDFdKSkge1xuICAgICAgICAgICAgICAgIGNsaXBwZWRMaW5lID0gW3AwXTtcbiAgICAgICAgICAgICAgICBjbGlwcGVkTGluZXMucHVzaChjbGlwcGVkTGluZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNsaXBwZWRMaW5lLnB1c2gocDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWRMaW5lcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3g7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveChhbmNob3IsIHgxLCB5MSwgeDIsIHkyLCBtYXhTY2FsZSkge1xuICAgIC8vIHRoZSBib3ggaXMgY2VudGVyZWQgYXJvdW5kIHRoZSBhbmNob3IgcG9pbnRcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcblxuICAgIC8vIGRpc3RhbmNlcyB0byB0aGUgZWRnZXMgZnJvbSB0aGUgYW5jaG9yXG4gICAgdGhpcy54MSA9IHgxO1xuICAgIHRoaXMueTEgPSB5MTtcbiAgICB0aGlzLngyID0geDI7XG4gICAgdGhpcy55MiA9IHkyO1xuXG4gICAgLy8gdGhlIGJveCBpcyBvbmx5IHZhbGlkIGZvciBzY2FsZXMgPCBtYXhTY2FsZS5cbiAgICAvLyBUaGUgYm94IGRvZXMgbm90IGJsb2NrIG90aGVyIGJveGVzIGF0IHNjYWxlcyA+PSBtYXhTY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG5cbiAgICAvLyB0aGUgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIGNhbiBmaXJzdCBiZSBzaG93blxuICAgIHRoaXMucGxhY2VtZW50U2NhbGUgPSAwO1xuXG4gICAgLy8gcm90YXRlZCBhbmQgc2NhbGVkIGJib3ggdXNlZCBmb3IgaW5kZXhpbmdcbiAgICB0aGlzWzBdID0gdGhpc1sxXSA9IHRoaXNbMl0gPSB0aGlzWzNdID0gMDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbGxpc2lvbkJveCA9IHJlcXVpcmUoJy4vY29sbGlzaW9uX2JveCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxpc2lvbkZlYXR1cmU7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkZlYXR1cmUobGluZSwgYW5jaG9yLCBzaGFwZWQsIGJveFNjYWxlLCBwYWRkaW5nLCBhbGlnbkxpbmUpIHtcblxuICAgIHZhciB5MSA9IHNoYXBlZC50b3AgKiBib3hTY2FsZSAtIHBhZGRpbmc7XG4gICAgdmFyIHkyID0gc2hhcGVkLmJvdHRvbSAqIGJveFNjYWxlICsgcGFkZGluZztcbiAgICB2YXIgeDEgPSBzaGFwZWQubGVmdCAqIGJveFNjYWxlIC0gcGFkZGluZztcbiAgICB2YXIgeDIgPSBzaGFwZWQucmlnaHQgKiBib3hTY2FsZSArIHBhZGRpbmc7XG5cbiAgICB0aGlzLmJveGVzID0gW107XG5cbiAgICBpZiAoYWxpZ25MaW5lKSB7XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IHkyIC0geTE7XG4gICAgICAgIHZhciBsZW5ndGggPSB4MiAtIHgxO1xuXG4gICAgICAgIGlmIChoZWlnaHQgPD0gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIHNldCBtaW5pbXVtIGJveCBoZWlnaHQgdG8gYXZvaWQgdmVyeSBtYW55IHNtYWxsIGxhYmVsc1xuICAgICAgICBoZWlnaHQgPSBNYXRoLm1heCgxMCAqIGJveFNjYWxlLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuYmJveGlmeUxhYmVsKGxpbmUsIGFuY2hvciwgbGVuZ3RoLCBoZWlnaHQpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ib3hlcy5wdXNoKG5ldyBDb2xsaXNpb25Cb3goYW5jaG9yLCB4MSwgeTEsIHgyLCB5MiwgSW5maW5pdHkpKTtcbiAgICB9XG59XG5cbkNvbGxpc2lvbkZlYXR1cmUucHJvdG90eXBlLmJib3hpZnlMYWJlbCA9IGZ1bmN0aW9uKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIGJveFNpemUpIHtcbiAgICB2YXIgc3RlcCA9IGJveFNpemUgLyAyO1xuICAgIHZhciBuQm94ZXMgPSBNYXRoLmZsb29yKGxhYmVsTGVuZ3RoIC8gc3RlcCk7XG5cbiAgICAvLyBvZmZzZXQgdGhlIGNlbnRlciBvZiB0aGUgZmlyc3QgYm94IGJ5IGhhbGYgYSBib3ggc28gdGhhdCB0aGUgZWRnZSBvZiB0aGVcbiAgICAvLyBib3ggaXMgYXQgdGhlIGVkZ2Ugb2YgdGhlIGxhYmVsLlxuICAgIHZhciBmaXJzdEJveE9mZnNldCA9IC1ib3hTaXplIC8gMjtcblxuICAgIHZhciBiYm94ZXMgPSB0aGlzLmJveGVzO1xuXG4gICAgdmFyIHAgPSBhbmNob3I7XG4gICAgdmFyIGluZGV4ID0gYW5jaG9yLnNlZ21lbnQgKyAxO1xuICAgIHZhciBhbmNob3JEaXN0YW5jZSA9IGZpcnN0Qm94T2Zmc2V0O1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICBkbyB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIC8vIGNoZWNrTWF4QW5nbGUgc2hvdWxkIGhhdmUgYWxyZWFkeSBjYXVnaHQgdGhpc1xuICAgICAgICBpZiAoaW5kZXggPCAwKSByZXR1cm4gYmJveGVzO1xuXG4gICAgICAgIGFuY2hvckRpc3RhbmNlIC09IGxpbmVbaW5kZXhdLmRpc3QocCk7XG4gICAgICAgIHAgPSBsaW5lW2luZGV4XTtcbiAgICB9IHdoaWxlIChhbmNob3JEaXN0YW5jZSA+IC1sYWJlbExlbmd0aCAvIDIpO1xuXG4gICAgdmFyIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5Cb3hlczsgaSsrKSB7XG4gICAgICAgIC8vIHRoZSBkaXN0YW5jZSB0aGUgYm94IHdpbGwgYmUgZnJvbSB0aGUgYW5jaG9yXG4gICAgICAgIHZhciBib3hEaXN0YW5jZVRvQW5jaG9yID0gLWxhYmVsTGVuZ3RoIC8gMiArIGkgKiBzdGVwO1xuXG4gICAgICAgIC8vIHRoZSBib3ggaXMgbm90IG9uIHRoZSBjdXJyZW50IHNlZ21lbnQuIE1vdmUgdG8gdGhlIG5leHQgc2VnbWVudC5cbiAgICAgICAgd2hpbGUgKGFuY2hvckRpc3RhbmNlICsgc2VnbWVudExlbmd0aCA8IGJveERpc3RhbmNlVG9BbmNob3IpIHtcbiAgICAgICAgICAgIGFuY2hvckRpc3RhbmNlICs9IHNlZ21lbnRMZW5ndGg7XG4gICAgICAgICAgICBpbmRleCsrO1xuXG4gICAgICAgICAgICAvLyBUaGVyZSBpc24ndCBlbm91Z2ggcm9vbSBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgbGluZS5cbiAgICAgICAgICAgIGlmIChpbmRleCArIDEgPj0gbGluZS5sZW5ndGgpIHJldHVybiBiYm94ZXM7XG5cbiAgICAgICAgICAgIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgZGlzdGFuY2UgdGhlIGJveCB3aWxsIGJlIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc2VnbWVudFxuICAgICAgICB2YXIgc2VnbWVudEJveERpc3RhbmNlID0gYm94RGlzdGFuY2VUb0FuY2hvciAtIGFuY2hvckRpc3RhbmNlO1xuXG4gICAgICAgIHZhciBwMCA9IGxpbmVbaW5kZXhdO1xuICAgICAgICB2YXIgcDEgPSBsaW5lW2luZGV4ICsgMV07XG4gICAgICAgIHZhciBib3hBbmNob3IgPSBwMS5zdWIocDApLl91bml0KCkuX211bHQoc2VnbWVudEJveERpc3RhbmNlKS5fYWRkKHAwKTtcblxuICAgICAgICB2YXIgZGlzdGFuY2VUb0lubmVyRWRnZSA9IE1hdGgubWF4KE1hdGguYWJzKGJveERpc3RhbmNlVG9BbmNob3IgLSBmaXJzdEJveE9mZnNldCkgLSBzdGVwIC8gMiwgMCk7XG4gICAgICAgIHZhciBtYXhTY2FsZSA9IGxhYmVsTGVuZ3RoIC8gMiAvIGRpc3RhbmNlVG9Jbm5lckVkZ2U7XG5cbiAgICAgICAgYmJveGVzLnB1c2gobmV3IENvbGxpc2lvbkJveChib3hBbmNob3IsIC1ib3hTaXplIC8gMiwgLWJveFNpemUgLyAyLCBib3hTaXplIC8gMiwgYm94U2l6ZSAvIDIsIG1heFNjYWxlKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJib3hlcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByYnVzaCA9IHJlcXVpcmUoJ3JidXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sbGlzaW9uVGlsZTtcblxuZnVuY3Rpb24gQ29sbGlzaW9uVGlsZSh6b29tLCB0aWxlRXh0ZW50LCB0aWxlU2l6ZSkge1xuICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgdGhpcy50aWxlUGl4ZWxSYXRpbyA9IHRpbGVFeHRlbnQgLyB0aWxlU2l6ZTtcbn1cblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWluU2NhbGUgPSAwLjI1O1xuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWF4U2NhbGUgPSAyO1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCkge1xuICAgIHRoaXMudHJlZSA9IHJidXNoKCk7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHRoaXMucm90YXRpb25NYXRyaXggPSBbY29zLCAtc2luLCBzaW4sIGNvc107XG5cbiAgICAvLyBTdHJldGNoIGJveGVzIGluIHkgZGlyZWN0aW9uIHRvIGFjY291bnQgZm9yIHRoZSBtYXAgdGlsdC5cbiAgICB0aGlzLnlTdHJldGNoID0gMSAvIE1hdGguY29zKHBpdGNoIC8gMTgwICogTWF0aC5QSSk7XG5cbiAgICAvLyBUaGUgYW1vdW50IHRoZSBtYXAgaXMgc3F1aXNoZWQgZGVwZW5kcyBvbiB0aGUgeSBwb3NpdGlvbi5cbiAgICAvLyBTb3J0IG9mIGFjY291bnQgZm9yIHRoaXMgYnkgbWFraW5nIGFsbCBib3hlcyBhIGJpdCBiaWdnZXIuXG4gICAgdGhpcy55U3RyZXRjaCA9IE1hdGgucG93KHRoaXMueVN0cmV0Y2gsIDEuMyk7XG59O1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5wbGFjZUZlYXR1cmUgPSBmdW5jdGlvbihmZWF0dXJlKSB7XG5cbiAgICB2YXIgbWluUGxhY2VtZW50U2NhbGUgPSB0aGlzLm1pblNjYWxlO1xuICAgIHZhciByb3RhdGlvbk1hdHJpeCA9IHRoaXMucm90YXRpb25NYXRyaXg7XG4gICAgdmFyIHlTdHJldGNoID0gdGhpcy55U3RyZXRjaDtcblxuICAgIGZvciAodmFyIGIgPSAwOyBiIDwgZmVhdHVyZS5ib3hlcy5sZW5ndGg7IGIrKykge1xuXG4gICAgICAgIHZhciBib3ggPSBmZWF0dXJlLmJveGVzW2JdO1xuXG4gICAgICAgIHZhciBhbmNob3IgPSBib3guYW5jaG9yLm1hdE11bHQocm90YXRpb25NYXRyaXgpO1xuICAgICAgICB2YXIgeCA9IGFuY2hvci54O1xuICAgICAgICB2YXIgeSA9IGFuY2hvci55O1xuXG4gICAgICAgIGJveFswXSA9IHggKyBib3gueDE7XG4gICAgICAgIGJveFsxXSA9IHkgKyBib3gueTEgKiB5U3RyZXRjaDtcbiAgICAgICAgYm94WzJdID0geCArIGJveC54MjtcbiAgICAgICAgYm94WzNdID0geSArIGJveC55MiAqIHlTdHJldGNoO1xuXG4gICAgICAgIHZhciBibG9ja2luZ0JveGVzID0gdGhpcy50cmVlLnNlYXJjaChib3gpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tpbmdCb3hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJsb2NraW5nID0gYmxvY2tpbmdCb3hlc1tpXTtcbiAgICAgICAgICAgIHZhciBibG9ja2luZ0FuY2hvciA9IGJsb2NraW5nLmFuY2hvci5tYXRNdWx0KHJvdGF0aW9uTWF0cml4KTtcblxuICAgICAgICAgICAgLy8gRmluZCB0aGUgbG93ZXN0IHNjYWxlIGF0IHdoaWNoIHRoZSB0d28gYm94ZXMgY2FuIGZpdCBzaWRlIGJ5IHNpZGUgd2l0aG91dCBvdmVybGFwcGluZy5cbiAgICAgICAgICAgIC8vIE9yaWdpbmFsIGFsZ29yaXRobTpcbiAgICAgICAgICAgIHZhciBzMSA9IChibG9ja2luZy54MSAtIGJveC54MikgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSBsZWZ0IG9mIG9sZCBib3hcbiAgICAgICAgICAgIHZhciBzMiA9IChibG9ja2luZy54MiAtIGJveC54MSkgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSByaWdodCBvZiBvbGQgYm94XG4gICAgICAgICAgICB2YXIgczMgPSAoYmxvY2tpbmcueTEgLSBib3gueTIpICogeVN0cmV0Y2ggLyAoeSAtIGJsb2NraW5nQW5jaG9yLnkpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSB0b3Agb2Ygb2xkIGJveFxuICAgICAgICAgICAgdmFyIHM0ID0gKGJsb2NraW5nLnkyIC0gYm94LnkxKSAqIHlTdHJldGNoIC8gKHkgLSBibG9ja2luZ0FuY2hvci55KTsgLy8gc2NhbGUgYXQgd2hpY2ggbmV3IGJveCBpcyB0byB0aGUgYm90dG9tIG9mIG9sZCBib3hcblxuICAgICAgICAgICAgaWYgKGlzTmFOKHMxKSB8fCBpc05hTihzMikpIHMxID0gczIgPSAxO1xuICAgICAgICAgICAgaWYgKGlzTmFOKHMzKSB8fCBpc05hTihzNCkpIHMzID0gczQgPSAxO1xuXG4gICAgICAgICAgICB2YXIgY29sbGlzaW9uRnJlZVNjYWxlID0gTWF0aC5taW4oTWF0aC5tYXgoczEsIHMyKSwgTWF0aC5tYXgoczMsIHM0KSk7XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBibG9ja2luZy5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIEFmdGVyIGEgYm94J3MgbWF4U2NhbGUgdGhlIGxhYmVsIGhhcyBzaHJ1bmsgZW5vdWdoIHRoYXQgdGhlIGJveCBpcyBubyBsb25nZXIgbmVlZGVkIHRvIGNvdmVyIGl0LFxuICAgICAgICAgICAgICAgIC8vIHNvIHVuYmxvY2sgdGhlIG5ldyBib3ggYXQgdGhlIHNjYWxlIHRoYXQgdGhlIG9sZCBib3ggZGlzYXBwZWFycy5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBibG9ja2luZy5tYXhTY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbGxpc2lvbkZyZWVTY2FsZSA+IGJveC5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBib3ggY2FuIG9ubHkgYmUgc2hvd24gYWZ0ZXIgaXQgaXMgdmlzaWJsZSwgdGhlbiB0aGUgYm94IGNhbiBuZXZlciBiZSBzaG93bi5cbiAgICAgICAgICAgICAgICAvLyBCdXQgdGhlIGxhYmVsIGNhbiBiZSBzaG93biBhZnRlciB0aGlzIGJveCBpcyBub3QgdmlzaWJsZS5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBib3gubWF4U2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBtaW5QbGFjZW1lbnRTY2FsZSAmJlxuICAgICAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPj0gYmxvY2tpbmcucGxhY2VtZW50U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGNvbGxpc2lvbiBvY2N1cnMgYXQgYSBsb3dlciBzY2FsZSB0aGFuIHByZXZpb3VzbHkgZm91bmQgY29sbGlzaW9uc1xuICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgY29sbGlzaW9uIG9jY3VycyB3aGlsZSB0aGUgb3RoZXIgbGFiZWwgaXMgdmlzaWJsZVxuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB0aGlzIGlzIHRoZSBsb3dlc3Qgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIHdvbid0IGNvbGxpZGUgd2l0aCBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIG1pblBsYWNlbWVudFNjYWxlID0gY29sbGlzaW9uRnJlZVNjYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPj0gdGhpcy5tYXhTY2FsZSkgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xufTtcblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUuaW5zZXJ0RmVhdHVyZSA9IGZ1bmN0aW9uKGZlYXR1cmUsIG1pblBsYWNlbWVudFNjYWxlKSB7XG5cbiAgICB2YXIgYm94ZXMgPSBmZWF0dXJlLmJveGVzO1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYm94ZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgYm94ZXNba10ucGxhY2VtZW50U2NhbGUgPSBtaW5QbGFjZW1lbnRTY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPCB0aGlzLm1heFNjYWxlKSB7XG4gICAgICAgIHRoaXMudHJlZS5sb2FkKGJveGVzKTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW50ZXJwb2xhdGUgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyk7XG52YXIgQW5jaG9yID0gcmVxdWlyZSgnLi4vc3ltYm9sL2FuY2hvcicpO1xudmFyIGNoZWNrTWF4QW5nbGUgPSByZXF1aXJlKCcuL2NoZWNrX21heF9hbmdsZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEFuY2hvcnM7XG5cbmZ1bmN0aW9uIGdldEFuY2hvcnMobGluZSwgc3BhY2luZywgbWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgYm94U2NhbGUsIG92ZXJzY2FsaW5nKSB7XG5cbiAgICAvLyBSZXNhbXBsZSBhIGxpbmUgdG8gZ2V0IGFuY2hvciBwb2ludHMgZm9yIGxhYmVscyBhbmQgY2hlY2sgdGhhdCBlYWNoXG4gICAgLy8gcG90ZW50aWFsIGxhYmVsIHBhc3NlcyB0ZXh0LW1heC1hbmdsZSBjaGVjayBhbmQgaGFzIGVub3VnaCBmcm9vbSB0byBmaXRcbiAgICAvLyBvbiB0aGUgbGluZS5cblxuICAgIHZhciBhbmdsZVdpbmRvd1NpemUgPSBzaGFwZWRUZXh0ID9cbiAgICAgICAgMyAvIDUgKiBnbHlwaFNpemUgKiBib3hTY2FsZSA6XG4gICAgICAgIDA7XG5cbiAgICAvLyBPZmZzZXQgdGhlIGZpcnN0IGFuY2hvciBieSBoYWxmIHRoZSBsYWJlbCBsZW5ndGggKG9yIGhhbGYgdGhlIHNwYWNpbmcgZGlzdGFuY2UgZm9yIGljb25zKS5cbiAgICAvLyBBZGQgYSBiaXQgb2YgZXh0cmEgb2Zmc2V0IHRvIGF2b2lkIGNvbGxpc2lvbnMgYXQgVCBpbnRlcnNlY3Rpb25zLlxuICAgIHZhciBsYWJlbExlbmd0aCA9IHNoYXBlZFRleHQgPyBzaGFwZWRUZXh0LnJpZ2h0IC0gc2hhcGVkVGV4dC5sZWZ0IDogc3BhY2luZztcbiAgICB2YXIgZXh0cmFPZmZzZXQgPSBnbHlwaFNpemUgKiAyO1xuICAgIHZhciBvZmZzZXQgPSAoKGxhYmVsTGVuZ3RoIC8gMiArIGV4dHJhT2Zmc2V0KSAqIGJveFNjYWxlICogb3ZlcnNjYWxpbmcpICUgc3BhY2luZztcblxuICAgIHJldHVybiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoICogYm94U2NhbGUsIGZhbHNlKTtcbn1cblxuXG5mdW5jdGlvbiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoLCBwbGFjZUF0TWlkZGxlKSB7XG5cbiAgICB2YXIgZGlzdGFuY2UgPSAwLFxuICAgICAgICBtYXJrZWREaXN0YW5jZSA9IG9mZnNldCA/IG9mZnNldCAtIHNwYWNpbmcgOiAwO1xuXG4gICAgdmFyIGFuY2hvcnMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZS5sZW5ndGggLSAxOyBpKyspIHtcblxuICAgICAgICB2YXIgYSA9IGxpbmVbaV0sXG4gICAgICAgICAgICBiID0gbGluZVtpICsgMV07XG5cbiAgICAgICAgdmFyIHNlZ21lbnREaXN0ID0gYS5kaXN0KGIpLFxuICAgICAgICAgICAgYW5nbGUgPSBiLmFuZ2xlVG8oYSk7XG5cbiAgICAgICAgd2hpbGUgKG1hcmtlZERpc3RhbmNlICsgc3BhY2luZyA8IGRpc3RhbmNlICsgc2VnbWVudERpc3QpIHtcbiAgICAgICAgICAgIG1hcmtlZERpc3RhbmNlICs9IHNwYWNpbmc7XG5cbiAgICAgICAgICAgIHZhciB0ID0gKG1hcmtlZERpc3RhbmNlIC0gZGlzdGFuY2UpIC8gc2VnbWVudERpc3QsXG4gICAgICAgICAgICAgICAgeCA9IGludGVycG9sYXRlKGEueCwgYi54LCB0KSxcbiAgICAgICAgICAgICAgICB5ID0gaW50ZXJwb2xhdGUoYS55LCBiLnksIHQpO1xuXG4gICAgICAgICAgICBpZiAoeCA+PSAwICYmIHggPCA0MDk2ICYmIHkgPj0gMCAmJiB5IDwgNDA5Nikge1xuICAgICAgICAgICAgICAgIHggPSBNYXRoLnJvdW5kKHgpO1xuICAgICAgICAgICAgICAgIHkgPSBNYXRoLnJvdW5kKHkpO1xuICAgICAgICAgICAgICAgIHZhciBhbmNob3IgPSBuZXcgQW5jaG9yKHgsIHksIGFuZ2xlLCBpKTtcblxuICAgICAgICAgICAgICAgIGlmICghYW5nbGVXaW5kb3dTaXplIHx8IGNoZWNrTWF4QW5nbGUobGluZSwgYW5jaG9yLCBsYWJlbExlbmd0aCwgYW5nbGVXaW5kb3dTaXplLCBtYXhBbmdsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9ycy5wdXNoKGFuY2hvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGlzdGFuY2UgKz0gc2VnbWVudERpc3Q7XG4gICAgfVxuXG4gICAgaWYgKCFwbGFjZUF0TWlkZGxlICYmICFhbmNob3JzLmxlbmd0aCkge1xuICAgICAgICAvLyBUaGUgZmlyc3QgYXR0ZW1wdCBhdCBmaW5kaW5nIGFuY2hvcnMgYXQgd2hpY2ggbGFiZWxzIGNhbiBiZSBwbGFjZWQgZmFpbGVkLlxuICAgICAgICAvLyBUcnkgYWdhaW4sIGJ1dCB0aGlzIHRpbWUganVzdCB0cnkgcGxhY2luZyBvbmUgYW5jaG9yIGF0IHRoZSBtaWRkbGUgb2YgdGhlIGxpbmUuXG4gICAgICAgIC8vIFRoaXMgaGFzIHRoZSBtb3N0IGVmZmVjdCBmb3Igc2hvcnQgbGluZXMgaW4gb3ZlcnNjYWxlZCB0aWxlcywgc2luY2UgdGhlXG4gICAgICAgIC8vIGluaXRpYWwgb2Zmc2V0IHVzZWQgaW4gb3ZlcnNjYWxlZCB0aWxlcyBpcyBjYWxjdWxhdGVkIHRvIGFsaWduIGxhYmVscyB3aXRoIHBvc2l0aW9ucyBpblxuICAgICAgICAvLyBwYXJlbnQgdGlsZXMgaW5zdGVhZCBvZiBwbGFjaW5nIHRoZSBsYWJlbCBhcyBjbG9zZSB0byB0aGUgYmVnaW5uaW5nIGFzIHBvc3NpYmxlLlxuICAgICAgICBhbmNob3JzID0gcmVzYW1wbGUobGluZSwgZGlzdGFuY2UgLyAyLCBzcGFjaW5nLCBhbmdsZVdpbmRvd1NpemUsIG1heEFuZ2xlLCBsYWJlbExlbmd0aCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuY2hvcnM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCaW5QYWNrID0gcmVxdWlyZSgnLi9iaW5fcGFjaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoQXRsYXM7XG5mdW5jdGlvbiBHbHlwaEF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW5kZXggPSB7fTtcbiAgICB0aGlzLmlkcyA9IHt9O1xuICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbn1cblxuR2x5cGhBdGxhcy5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGRlYnVnKCkge1xuICAgICAgICByZXR1cm4gJ2NhbnZhcycgaW4gdGhpcztcbiAgICB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgJiYgIXRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuZ2V0R2x5cGhzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdseXBocyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghZ2x5cGhzW25hbWVdKSBnbHlwaHNbbmFtZV0gPSBbXTtcbiAgICAgICAgZ2x5cGhzW25hbWVdLnB1c2goaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBnbHlwaHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5nZXRSZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWN0cyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghcmVjdHNbbmFtZV0pIHJlY3RzW25hbWVdID0ge307XG4gICAgICAgIHJlY3RzW25hbWVdW2lkXSA9IHRoaXMuaW5kZXhba2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5yZW1vdmVHbHlwaHMgPSBmdW5jdGlvbihpZCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmlkcykge1xuXG4gICAgICAgIHZhciBpZHMgPSB0aGlzLmlkc1trZXldO1xuXG4gICAgICAgIHZhciBwb3MgPSBpZHMuaW5kZXhPZihpZCk7XG4gICAgICAgIGlmIChwb3MgPj0gMCkgaWRzLnNwbGljZShwb3MsIDEpO1xuICAgICAgICB0aGlzLmlkc1trZXldID0gaWRzO1xuXG4gICAgICAgIGlmICghaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHJlY3QgPSB0aGlzLmluZGV4W2tleV07XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHJlY3QuaDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5KSArIHJlY3QueDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHJlY3QudzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmJpbi5yZWxlYXNlKHJlY3QpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pbmRleFtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWRzW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHRoaXMudXBkYXRlVGV4dHVyZSh0aGlzLmdsKTtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmFkZEdseXBoID0gZnVuY3Rpb24oaWQsIG5hbWUsIGdseXBoLCBidWZmZXIpIHtcbiAgICBpZiAoIWdseXBoKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignbWlzc2luZyBnbHlwaCcsIGNvZGUsIFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIGtleSA9IG5hbWUgKyBcIiNcIiArIGdseXBoLmlkO1xuXG4gICAgLy8gVGhlIGdseXBoIGlzIGFscmVhZHkgaW4gdGhpcyB0ZXh0dXJlLlxuICAgIGlmICh0aGlzLmluZGV4W2tleV0pIHtcbiAgICAgICAgaWYgKHRoaXMuaWRzW2tleV0uaW5kZXhPZihpZCkgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmlkc1trZXldLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZGV4W2tleV07XG4gICAgfVxuXG4gICAgLy8gVGhlIGdseXBoIGJpdG1hcCBoYXMgemVybyB3aWR0aC5cbiAgICBpZiAoIWdseXBoLmJpdG1hcCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYnVmZmVyZWRXaWR0aCA9IGdseXBoLndpZHRoICsgYnVmZmVyICogMjtcbiAgICB2YXIgYnVmZmVyZWRIZWlnaHQgPSBnbHlwaC5oZWlnaHQgKyBidWZmZXIgKiAyO1xuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuICAgIHZhciBwYWNrV2lkdGggPSBidWZmZXJlZFdpZHRoICsgMiAqIHBhZGRpbmc7XG4gICAgdmFyIHBhY2tIZWlnaHQgPSBidWZmZXJlZEhlaWdodCArIDIgKiBwYWRkaW5nO1xuXG4gICAgLy8gSW5jcmVhc2UgdG8gbmV4dCBudW1iZXIgZGl2aXNpYmxlIGJ5IDQsIGJ1dCBhdCBsZWFzdCAxLlxuICAgIC8vIFRoaXMgaXMgc28gd2UgY2FuIHNjYWxlIGRvd24gdGhlIHRleHR1cmUgY29vcmRpbmF0ZXMgYW5kIHBhY2sgdGhlbVxuICAgIC8vIGludG8gMiBieXRlcyByYXRoZXIgdGhhbiA0IGJ5dGVzLlxuICAgIHBhY2tXaWR0aCArPSAoNCAtIHBhY2tXaWR0aCAlIDQpO1xuICAgIHBhY2tIZWlnaHQgKz0gKDQgLSBwYWNrSGVpZ2h0ICUgNCk7XG5cbiAgICB2YXIgcmVjdCA9IHRoaXMuYmluLmFsbG9jYXRlKHBhY2tXaWR0aCwgcGFja0hlaWdodCk7XG4gICAgaWYgKHJlY3QueCA8IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdnbHlwaCBiaXRtYXAgb3ZlcmZsb3cnKTtcbiAgICAgICAgcmV0dXJuIHsgZ2x5cGg6IGdseXBoLCByZWN0OiBudWxsIH07XG4gICAgfVxuXG4gICAgdGhpcy5pbmRleFtrZXldID0gcmVjdDtcbiAgICB0aGlzLmlkc1trZXldID0gW2lkXTtcblxuICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgdmFyIHNvdXJjZSA9IGdseXBoLmJpdG1hcDtcbiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGJ1ZmZlcmVkSGVpZ2h0OyB5KyspIHtcbiAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5ICsgcGFkZGluZykgKyByZWN0LnggKyBwYWRkaW5nO1xuICAgICAgICB2YXIgeTIgPSBidWZmZXJlZFdpZHRoICogeTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBidWZmZXJlZFdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gc291cmNlW3kyICsgeF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcblxuICAgIHJldHVybiByZWN0O1xufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgdGhpcy5nbCA9IGdsO1xuICAgIGlmICghdGhpcy50ZXh0dXJlKSB7XG4gICAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuQUxQSEEsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCAwLCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgIH1cbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLnVwZGF0ZVRleHR1cmUgPSBmdW5jdGlvbihnbCkge1xuICAgIHRoaXMuYmluZChnbCk7XG4gICAgaWYgKHRoaXMuZGlydHkpIHtcblxuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy5kYXRhKTtcblxuICAgICAgICAvLyBERUJVR1xuICAgICAgICBpZiAodGhpcy5jdHgpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gdGhpcy5jdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKywgaiArPSA0KSB7XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2pdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICAgICAgICAgIGRhdGEuZGF0YVtqICsgMV0gPSB0aGlzLmRhdGFbaV07XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2ogKyAyXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaiArIDNdID0gMjU1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54LCBmcmVlLnksIGZyZWUudywgZnJlZS5oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcblxuICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplR2x5cGhzVVJMO1xudmFyIGdldEFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4JykuZ2V0QXJyYXlCdWZmZXI7XG52YXIgR2x5cGhzID0gcmVxdWlyZSgnLi4vdXRpbC9nbHlwaHMnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoU291cmNlO1xuXG4vKipcbiAqIEEgZ2x5cGggc291cmNlIGhhcyBhIFVSTCBmcm9tIHdoaWNoIHRvIGxvYWQgbmV3IGdseXBocyBhbmQgb3ducyBhIEdseXBoQXRsYXNcbiAqIHRoYXQgc3RvcmVzIGN1cnJlbnRseS1sb2FkZWQgZ2x5cGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgZ2x5cGggdGVtcGxhdGUgdXJsXG4gKiBAcGFyYW0ge09iamVjdH0gZ2x5cGhBdGxhcyBnbHlwaCBhdGxhcyBvYmplY3RcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEdseXBoU291cmNlKHVybCwgZ2x5cGhBdGxhcykge1xuICAgIHRoaXMudXJsID0gdXJsICYmIG5vcm1hbGl6ZVVSTCh1cmwpO1xuICAgIHRoaXMuZ2x5cGhBdGxhcyA9IGdseXBoQXRsYXM7XG4gICAgdGhpcy5zdGFja3MgPSBbXTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcbn1cblxuR2x5cGhTb3VyY2UucHJvdG90eXBlLmdldFNpbXBsZUdseXBocyA9IGZ1bmN0aW9uKGZvbnRzdGFjaywgZ2x5cGhJRHMsIHVpZCwgY2FsbGJhY2spIHtcblxuICAgIGlmICh0aGlzLnN0YWNrc1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10gPSB7fTtcblxuICAgIHZhciBnbHlwaHMgPSB7fTtcblxuICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja107XG4gICAgdmFyIGdseXBoQXRsYXMgPSB0aGlzLmdseXBoQXRsYXM7XG5cbiAgICAvLyB0aGUgbnVtYmVyIG9mIHBpeGVscyB0aGUgc2RmIGJpdG1hcHMgYXJlIHBhZGRlZCBieVxuICAgIHZhciBidWZmZXIgPSAzO1xuXG4gICAgdmFyIG1pc3NpbmcgPSB7fTtcbiAgICB2YXIgcmVtYWluaW5nID0gMDtcbiAgICB2YXIgcmFuZ2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdseXBoSURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnbHlwaElEID0gZ2x5cGhJRHNbaV07XG4gICAgICAgIHJhbmdlID0gTWF0aC5mbG9vcihnbHlwaElEIC8gMjU2KTtcblxuICAgICAgICBpZiAoc3RhY2tbcmFuZ2VdKSB7XG4gICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFja1tyYW5nZV0uZ2x5cGhzW2dseXBoSURdO1xuICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICBpZiAoZ2x5cGgpIGdseXBoc1tnbHlwaElEXSA9IG5ldyBTaW1wbGVHbHlwaChnbHlwaCwgcmVjdCwgYnVmZmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nW3JhbmdlXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1tyYW5nZV0gPSBbXTtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pc3NpbmdbcmFuZ2VdLnB1c2goZ2x5cGhJRCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXJlbWFpbmluZykgY2FsbGJhY2sodW5kZWZpbmVkLCBnbHlwaHMpO1xuXG4gICAgdmFyIG9uUmFuZ2VMb2FkZWQgPSBmdW5jdGlvbihlcnIsIHJhbmdlLCBkYXRhKSB7XG4gICAgICAgIC8vIFRPRE8gbm90IGJlIHNpbGVudCBhYm91dCBlcnJvcnNcbiAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja11bcmFuZ2VdID0gZGF0YS5zdGFja3NbMF07XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdbcmFuZ2VdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdseXBoSUQgPSBtaXNzaW5nW3JhbmdlXVtpXTtcbiAgICAgICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFjay5nbHlwaHNbZ2x5cGhJRF07XG4gICAgICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKGdseXBoKSBnbHlwaHNbZ2x5cGhJRF0gPSBuZXcgU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIGdseXBocyk7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgZm9yICh2YXIgciBpbiBtaXNzaW5nKSB7XG4gICAgICAgIHRoaXMubG9hZFJhbmdlKGZvbnRzdGFjaywgciwgb25SYW5nZUxvYWRlZCk7XG4gICAgfVxufTtcblxuLy8gQSBzaW1wbGlmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnbHlwaCBjb250YWluaW5nIG9ubHkgdGhlIHByb3BlcnRpZXMgbmVlZGVkIGZvciBzaGFwaW5nLlxuZnVuY3Rpb24gU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcikge1xuICAgIHZhciBwYWRkaW5nID0gMTtcbiAgICB0aGlzLmFkdmFuY2UgPSBnbHlwaC5hZHZhbmNlO1xuICAgIHRoaXMubGVmdCA9IGdseXBoLmxlZnQgLSBidWZmZXIgLSBwYWRkaW5nO1xuICAgIHRoaXMudG9wID0gZ2x5cGgudG9wICsgYnVmZmVyICsgcGFkZGluZztcbiAgICB0aGlzLnJlY3QgPSByZWN0O1xufVxuXG5HbHlwaFNvdXJjZS5wcm90b3R5cGUubG9hZFJhbmdlID0gZnVuY3Rpb24oZm9udHN0YWNrLCByYW5nZSwgY2FsbGJhY2spIHtcblxuICAgIGlmIChyYW5nZSAqIDI1NiA+IDY1NTM1KSByZXR1cm4gY2FsbGJhY2soJ2d5cGhzID4gNjU1MzUgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgaWYgKHRoaXMubG9hZGluZ1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMubG9hZGluZ1tmb250c3RhY2tdID0ge307XG4gICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbZm9udHN0YWNrXTtcblxuICAgIGlmIChsb2FkaW5nW3JhbmdlXSkge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXSA9IFtjYWxsYmFja107XG5cbiAgICAgICAgdmFyIHJhbmdlTmFtZSA9IChyYW5nZSAqIDI1NikgKyAnLScgKyAocmFuZ2UgKiAyNTYgKyAyNTUpO1xuICAgICAgICB2YXIgdXJsID0gZ2x5cGhVcmwoZm9udHN0YWNrLCByYW5nZU5hbWUsIHRoaXMudXJsKTtcblxuICAgICAgICBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgdmFyIGdseXBocyA9ICFlcnIgJiYgbmV3IEdseXBocyhuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1tyYW5nZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2FkaW5nW3JhbmdlXVtpXShlcnIsIHJhbmdlLCBnbHlwaHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGxvYWRpbmdbcmFuZ2VdO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFVzZSBDTkFNRSBzaGFyZGluZyB0byBsb2FkIGEgc3BlY2lmaWMgZ2x5cGggcmFuZ2Ugb3ZlciBhIHJhbmRvbWl6ZWRcbiAqIGJ1dCBjb25zaXN0ZW50IHN1YmRvbWFpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250c3RhY2sgY29tbWEtam9pbmVkIGZvbnRzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmFuZ2UgY29tbWEtam9pbmVkIHJhbmdlXG4gKiBAcGFyYW0ge3VybH0gdXJsIHRlbXBsYXRlZCB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3ViZG9tYWlucz1hYmNdIHN1YmRvbWFpbnMgYXMgYSBzdHJpbmcgd2hlcmUgZWFjaCBsZXR0ZXIgaXMgb25lLlxuICogQHJldHVybnMge3N0cmluZ30gYSB1cmwgdG8gbG9hZCB0aGF0IHNlY3Rpb24gb2YgZ2x5cGhzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBnbHlwaFVybChmb250c3RhY2ssIHJhbmdlLCB1cmwsIHN1YmRvbWFpbnMpIHtcbiAgICBzdWJkb21haW5zID0gc3ViZG9tYWlucyB8fCAnYWJjJztcblxuICAgIHJldHVybiB1cmxcbiAgICAgICAgLnJlcGxhY2UoJ3tzfScsIHN1YmRvbWFpbnNbZm9udHN0YWNrLmxlbmd0aCAlIHN1YmRvbWFpbnMubGVuZ3RoXSlcbiAgICAgICAgLnJlcGxhY2UoJ3tmb250c3RhY2t9JywgZm9udHN0YWNrKVxuICAgICAgICAucmVwbGFjZSgne3JhbmdlfScsIHJhbmdlKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmVhdHVyZXMsIHRleHRGZWF0dXJlcywgZ2VvbWV0cmllcykge1xuXG4gICAgdmFyIGxlZnRJbmRleCA9IHt9LFxuICAgICAgICByaWdodEluZGV4ID0ge30sXG4gICAgICAgIG1lcmdlZEZlYXR1cmVzID0gW10sXG4gICAgICAgIG1lcmdlZEdlb20gPSBbXSxcbiAgICAgICAgbWVyZ2VkVGV4dHMgPSBbXSxcbiAgICAgICAgbWVyZ2VkSW5kZXggPSAwLFxuICAgICAgICBrO1xuXG4gICAgZnVuY3Rpb24gYWRkKGspIHtcbiAgICAgICAgbWVyZ2VkRmVhdHVyZXMucHVzaChmZWF0dXJlc1trXSk7XG4gICAgICAgIG1lcmdlZEdlb20ucHVzaChnZW9tZXRyaWVzW2tdKTtcbiAgICAgICAgbWVyZ2VkVGV4dHMucHVzaCh0ZXh0RmVhdHVyZXNba10pO1xuICAgICAgICBtZXJnZWRJbmRleCsrO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKSB7XG4gICAgICAgIHZhciBpID0gcmlnaHRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgZGVsZXRlIHJpZ2h0SW5kZXhbbGVmdEtleV07XG4gICAgICAgIHJpZ2h0SW5kZXhbcmlnaHRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnBvcCgpO1xuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdID0gbWVyZ2VkR2VvbVtpXVswXS5jb25jYXQoZ2VvbVswXSk7XG4gICAgICAgIHJldHVybiBpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbUxlZnQobGVmdEtleSwgcmlnaHRLZXksIGdlb20pIHtcbiAgICAgICAgdmFyIGkgPSBsZWZ0SW5kZXhbcmlnaHRLZXldO1xuICAgICAgICBkZWxldGUgbGVmdEluZGV4W3JpZ2h0S2V5XTtcbiAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnNoaWZ0KCk7XG4gICAgICAgIG1lcmdlZEdlb21baV1bMF0gPSBnZW9tWzBdLmNvbmNhdChtZXJnZWRHZW9tW2ldWzBdKTtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0S2V5KHRleHQsIGdlb20sIG9uUmlnaHQpIHtcbiAgICAgICAgdmFyIHBvaW50ID0gb25SaWdodCA/IGdlb21bMF1bZ2VvbVswXS5sZW5ndGggLSAxXSA6IGdlb21bMF1bMF07XG4gICAgICAgIHJldHVybiB0ZXh0ICsgJzonICsgcG9pbnQueCArICc6JyArIHBvaW50Lnk7XG4gICAgfVxuXG4gICAgZm9yIChrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBnZW9tID0gZ2VvbWV0cmllc1trXSxcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0RmVhdHVyZXNba107XG5cbiAgICAgICAgaWYgKCF0ZXh0KSB7XG4gICAgICAgICAgICBhZGQoayk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsZWZ0S2V5ID0gZ2V0S2V5KHRleHQsIGdlb20pLFxuICAgICAgICAgICAgcmlnaHRLZXkgPSBnZXRLZXkodGV4dCwgZ2VvbSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKChsZWZ0S2V5IGluIHJpZ2h0SW5kZXgpICYmIChyaWdodEtleSBpbiBsZWZ0SW5kZXgpICYmIChyaWdodEluZGV4W2xlZnRLZXldICE9PSBsZWZ0SW5kZXhbcmlnaHRLZXldKSkge1xuICAgICAgICAgICAgLy8gZm91bmQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IGFkamFjZW50IHRvIGJvdGggZW5kcyBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZSBhbGwgdGhyZWVcbiAgICAgICAgICAgIHZhciBqID0gbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG4gICAgICAgICAgICB2YXIgaSA9IG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBtZXJnZWRHZW9tW2pdKTtcblxuICAgICAgICAgICAgZGVsZXRlIGxlZnRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSByaWdodEluZGV4W3JpZ2h0S2V5XTtcblxuICAgICAgICAgICAgcmlnaHRJbmRleFtnZXRLZXkodGV4dCwgbWVyZ2VkR2VvbVtpXSwgdHJ1ZSldID0gaTtcbiAgICAgICAgICAgIG1lcmdlZEdlb21bal0gPSBudWxsO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobGVmdEtleSBpbiByaWdodEluZGV4KSB7XG4gICAgICAgICAgICAvLyBmb3VuZCBtZXJnZWFibGUgbGluZSBhZGphY2VudCB0byB0aGUgc3RhcnQgb2YgdGhlIGN1cnJlbnQgbGluZSwgbWVyZ2VcbiAgICAgICAgICAgIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHJpZ2h0S2V5IGluIGxlZnRJbmRleCkge1xuICAgICAgICAgICAgLy8gZm91bmQgbWVyZ2VhYmxlIGxpbmUgYWRqYWNlbnQgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZVxuICAgICAgICAgICAgbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vIGFkamFjZW50IGxpbmVzLCBhZGQgYXMgYSBuZXcgaXRlbVxuICAgICAgICAgICAgYWRkKGspO1xuICAgICAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gbWVyZ2VkSW5kZXggLSAxO1xuICAgICAgICAgICAgcmlnaHRJbmRleFtyaWdodEtleV0gPSBtZXJnZWRJbmRleCAtIDE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmZWF0dXJlczogbWVyZ2VkRmVhdHVyZXMsXG4gICAgICAgIHRleHRGZWF0dXJlczogbWVyZ2VkVGV4dHMsXG4gICAgICAgIGdlb21ldHJpZXM6IG1lcmdlZEdlb21cbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEljb25RdWFkczogZ2V0SWNvblF1YWRzLFxuICAgIGdldEdseXBoUXVhZHM6IGdldEdseXBoUXVhZHNcbn07XG5cbnZhciBtaW5TY2FsZSA9IDAuNTsgLy8gdW5kZXJzY2FsZSBieSAxIHpvb20gbGV2ZWxcblxuZnVuY3Rpb24gU3ltYm9sUXVhZChhbmNob3IsIHRsLCB0ciwgYmwsIGJyLCB0ZXgsIGFuZ2xlLCBtaW5TY2FsZSwgbWF4U2NhbGUpIHtcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcbiAgICB0aGlzLnRsID0gdGw7XG4gICAgdGhpcy50ciA9IHRyO1xuICAgIHRoaXMuYmwgPSBibDtcbiAgICB0aGlzLmJyID0gYnI7XG4gICAgdGhpcy50ZXggPSB0ZXg7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuICAgIHRoaXMubWluU2NhbGUgPSBtaW5TY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG59XG5cbmZ1bmN0aW9uIGdldEljb25RdWFkcyhhbmNob3IsIHNoYXBlZEljb24sIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHJlY3QgPSBzaGFwZWRJY29uLmltYWdlLnJlY3Q7XG5cbiAgICB2YXIgYm9yZGVyID0gMTtcbiAgICB2YXIgbGVmdCA9IHNoYXBlZEljb24ubGVmdCAtIGJvcmRlcjtcbiAgICB2YXIgcmlnaHQgPSBsZWZ0ICsgcmVjdC53O1xuICAgIHZhciB0b3AgPSBzaGFwZWRJY29uLnRvcCAtIGJvcmRlcjtcbiAgICB2YXIgYm90dG9tID0gdG9wICsgcmVjdC5oO1xuICAgIHZhciB0bCA9IG5ldyBQb2ludChsZWZ0LCB0b3ApO1xuICAgIHZhciB0ciA9IG5ldyBQb2ludChyaWdodCwgdG9wKTtcbiAgICB2YXIgYnIgPSBuZXcgUG9pbnQocmlnaHQsIGJvdHRvbSk7XG4gICAgdmFyIGJsID0gbmV3IFBvaW50KGxlZnQsIGJvdHRvbSk7XG5cbiAgICB2YXIgYW5nbGUgPSBsYXlvdXRbJ2ljb24tcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIGlmIChhbG9uZ0xpbmUpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2FuY2hvci5zZWdtZW50XTtcbiAgICAgICAgYW5nbGUgKz0gTWF0aC5hdGFuMihhbmNob3IueSAtIHByZXYueSwgYW5jaG9yLnggLSBwcmV2LngpO1xuICAgIH1cblxuICAgIGlmIChhbmdsZSkge1xuICAgICAgICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpLFxuICAgICAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpLFxuICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgIHRsID0gdGwubWF0TXVsdChtYXRyaXgpO1xuICAgICAgICB0ciA9IHRyLm1hdE11bHQobWF0cml4KTtcbiAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgIGJyID0gYnIubWF0TXVsdChtYXRyaXgpO1xuICAgIH1cblxuICAgIHJldHVybiBbbmV3IFN5bWJvbFF1YWQoYW5jaG9yLCB0bCwgdHIsIGJsLCBiciwgc2hhcGVkSWNvbi5pbWFnZS5yZWN0LCAwLCBtaW5TY2FsZSwgSW5maW5pdHkpXTtcbn1cblxuZnVuY3Rpb24gZ2V0R2x5cGhRdWFkcyhhbmNob3IsIHNoYXBpbmcsIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHRleHRSb3RhdGUgPSBsYXlvdXRbJ3RleHQtcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBrZWVwVXByaWdodCA9IGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXTtcblxuICAgIHZhciBwb3NpdGlvbmVkR2x5cGhzID0gc2hhcGluZy5wb3NpdGlvbmVkR2x5cGhzO1xuICAgIHZhciBxdWFkcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2tdO1xuICAgICAgICB2YXIgZ2x5cGggPSBwb3NpdGlvbmVkR2x5cGguZ2x5cGg7XG4gICAgICAgIHZhciByZWN0ID0gZ2x5cGgucmVjdDtcblxuICAgICAgICBpZiAoIXJlY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjZW50ZXJYID0gKHBvc2l0aW9uZWRHbHlwaC54ICsgZ2x5cGguYWR2YW5jZSAvIDIpICogYm94U2NhbGU7XG5cbiAgICAgICAgdmFyIGdseXBoSW5zdGFuY2VzO1xuICAgICAgICB2YXIgbGFiZWxNaW5TY2FsZSA9IG1pblNjYWxlO1xuICAgICAgICBpZiAoYWxvbmdMaW5lKSB7XG4gICAgICAgICAgICBnbHlwaEluc3RhbmNlcyA9IFtdO1xuICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIDEpO1xuICAgICAgICAgICAgaWYgKGtlZXBVcHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IE1hdGgubWluKGxhYmVsTWluU2NhbGUsIGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIC0xKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdseXBoSW5zdGFuY2VzID0gW3tcbiAgICAgICAgICAgICAgICBhbmNob3I6IGFuY2hvcixcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICAgICAgYW5nbGU6IDAsXG4gICAgICAgICAgICAgICAgbWF4U2NhbGU6IEluZmluaXR5LFxuICAgICAgICAgICAgICAgIG1pblNjYWxlOiBtaW5TY2FsZVxuICAgICAgICAgICAgfV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeDEgPSBwb3NpdGlvbmVkR2x5cGgueCArIGdseXBoLmxlZnQsXG4gICAgICAgICAgICB5MSA9IHBvc2l0aW9uZWRHbHlwaC55IC0gZ2x5cGgudG9wLFxuICAgICAgICAgICAgeDIgPSB4MSArIHJlY3QudyxcbiAgICAgICAgICAgIHkyID0geTEgKyByZWN0LmgsXG5cbiAgICAgICAgICAgIG90bCA9IG5ldyBQb2ludCh4MSwgeTEpLFxuICAgICAgICAgICAgb3RyID0gbmV3IFBvaW50KHgyLCB5MSksXG4gICAgICAgICAgICBvYmwgPSBuZXcgUG9pbnQoeDEsIHkyKSxcbiAgICAgICAgICAgIG9iciA9IG5ldyBQb2ludCh4MiwgeTIpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2x5cGhJbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gZ2x5cGhJbnN0YW5jZXNbaV0sXG4gICAgICAgICAgICAgICAgdGwgPSBvdGwsXG4gICAgICAgICAgICAgICAgdHIgPSBvdHIsXG4gICAgICAgICAgICAgICAgYmwgPSBvYmwsXG4gICAgICAgICAgICAgICAgYnIgPSBvYnIsXG4gICAgICAgICAgICAgICAgYW5nbGUgPSBpbnN0YW5jZS5hbmdsZSArIHRleHRSb3RhdGU7XG5cbiAgICAgICAgICAgIGlmIChhbmdsZSkge1xuICAgICAgICAgICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgICAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgdHIgPSB0ci5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgbGFiZWwgZnJvbSBleHRlbmRpbmcgcGFzdCB0aGUgZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICB2YXIgZ2x5cGhNaW5TY2FsZSA9IE1hdGgubWF4KGluc3RhbmNlLm1pblNjYWxlLCBsYWJlbE1pblNjYWxlKTtcblxuICAgICAgICAgICAgdmFyIGdseXBoQW5nbGUgPSAoYW5jaG9yLmFuZ2xlICsgdGV4dFJvdGF0ZSArIGluc3RhbmNlLm9mZnNldCArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG4gICAgICAgICAgICBxdWFkcy5wdXNoKG5ldyBTeW1ib2xRdWFkKGluc3RhbmNlLmFuY2hvciwgdGwsIHRyLCBibCwgYnIsIHJlY3QsIGdseXBoQW5nbGUsIGdseXBoTWluU2NhbGUsIGluc3RhbmNlLm1heFNjYWxlKSk7XG5cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBxdWFkcztcbn1cblxuZnVuY3Rpb24gZ2V0U2VnbWVudEdseXBocyhnbHlwaHMsIGFuY2hvciwgb2Zmc2V0LCBsaW5lLCBzZWdtZW50LCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgdXBzaWRlRG93biA9IGRpcmVjdGlvbiA8IDA7XG5cbiAgICBpZiAob2Zmc2V0IDwgMCkgZGlyZWN0aW9uICo9IC0xO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHNlZ21lbnQrKztcblxuICAgIHZhciBuZXdBbmNob3IgPSBhbmNob3I7XG4gICAgdmFyIGVuZCA9IGxpbmVbc2VnbWVudF07XG4gICAgdmFyIHByZXZTY2FsZSA9IEluZmluaXR5O1xuXG4gICAgb2Zmc2V0ID0gTWF0aC5hYnMob2Zmc2V0KTtcblxuICAgIHZhciBwbGFjZW1lbnRTY2FsZSA9IG1pblNjYWxlO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgdmFyIGRpc3RhbmNlID0gbmV3QW5jaG9yLmRpc3QoZW5kKTtcbiAgICAgICAgdmFyIHNjYWxlID0gb2Zmc2V0IC8gZGlzdGFuY2U7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBhbmdsZSBvZiB0aGUgbGluZSBzZWdtZW50XG4gICAgICAgIHZhciBhbmdsZSA9IE1hdGguYXRhbjIoZW5kLnkgLSBuZXdBbmNob3IueSwgZW5kLnggLSBuZXdBbmNob3IueCk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPCAwKSBhbmdsZSArPSBNYXRoLlBJO1xuICAgICAgICBpZiAodXBzaWRlRG93bikgYW5nbGUgKz0gTWF0aC5QSTtcblxuICAgICAgICBnbHlwaHMucHVzaCh7XG4gICAgICAgICAgICBhbmNob3I6IG5ldyBBbmNob3IobmV3QW5jaG9yLngsIG5ld0FuY2hvci55LCBhbmNob3IuYW5nbGUpLFxuICAgICAgICAgICAgb2Zmc2V0OiB1cHNpZGVEb3duID8gTWF0aC5QSSA6IDAsXG4gICAgICAgICAgICBtaW5TY2FsZTogc2NhbGUsXG4gICAgICAgICAgICBtYXhTY2FsZTogcHJldlNjYWxlLFxuICAgICAgICAgICAgYW5nbGU6IChhbmdsZSArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHNjYWxlIDw9IHBsYWNlbWVudFNjYWxlKSBicmVhaztcblxuICAgICAgICBuZXdBbmNob3IgPSBlbmQ7XG5cbiAgICAgICAgLy8gc2tpcCBkdXBsaWNhdGUgbm9kZXNcbiAgICAgICAgd2hpbGUgKG5ld0FuY2hvci5lcXVhbHMoZW5kKSkge1xuICAgICAgICAgICAgc2VnbWVudCArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICBlbmQgPSBsaW5lW3NlZ21lbnRdO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdW5pdCA9IGVuZC5zdWIobmV3QW5jaG9yKS5fdW5pdCgpO1xuICAgICAgICBuZXdBbmNob3IgPSBuZXdBbmNob3Iuc3ViKHVuaXQuX211bHQoZGlzdGFuY2UpKTtcblxuICAgICAgICBwcmV2U2NhbGUgPSBzY2FsZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2VtZW50U2NhbGU7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVJY29ucztcblxuLy8gRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGljb25zIG5lZWQgdG8gYmUgbG9hZGVkLlxuZnVuY3Rpb24gcmVzb2x2ZUljb25zKGZlYXR1cmVzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdmFyIGljb25zID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWydpY29uLWltYWdlJ10pO1xuICAgICAgICBpZiAoIXRleHQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChpY29ucy5pbmRleE9mKHRleHQpIDwgMCkge1xuICAgICAgICAgICAgaWNvbnMucHVzaCh0ZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpY29ucztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVzb2x2ZVRleHQ7XG5cbi8qKlxuICogRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGdseXBoIHJhbmdlcyBuZWVkIHRvIGJlIGxvYWRlZFxuICogYW5kIGFwcGx5IGFueSB0ZXh0IHByZXByb2Nlc3NpbmcuIFRoZSByZW1haW5pbmcgdXNlcnMgb2YgdGV4dCBzaG91bGRcbiAqIHVzZSB0aGUgYHRleHRGZWF0dXJlc2Aga2V5IHJldHVybmVkIGJ5IHRoaXMgZnVuY3Rpb24gcmF0aGVyIHRoYW4gYWNjZXNzaW5nXG4gKiBmZWF0dXJlIHRleHQgZGlyZWN0bHkuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZXNvbHZlVGV4dChmZWF0dXJlcywgbGF5b3V0UHJvcGVydGllcywgZ2x5cGhzKSB7XG4gICAgdmFyIHRleHRGZWF0dXJlcyA9IFtdO1xuICAgIHZhciBjb2RlcG9pbnRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZpZWxkJ10pO1xuICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgIHRleHRGZWF0dXJlc1tpXSA9IG51bGw7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0ID0gdGV4dC50b1N0cmluZygpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LXRyYW5zZm9ybSddO1xuICAgICAgICBpZiAodHJhbnNmb3JtID09PSAndXBwZXJjYXNlJykge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQudG9Mb2NhbGVVcHBlckNhc2UoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2Zvcm0gPT09ICdsb3dlcmNhc2UnKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpsID0gdGV4dC5sZW5ndGg7IGogPCBqbDsgaisrKSB7XG4gICAgICAgICAgICBjb2RlcG9pbnRzLnB1c2godGV4dC5jaGFyQ29kZUF0KGopKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIGluZGV4ZXMgb2YgZmVhdHVyZXMgd2l0aCB0ZXh0LlxuICAgICAgICB0ZXh0RmVhdHVyZXNbaV0gPSB0ZXh0O1xuICAgIH1cblxuICAgIC8vIGdldCBhIGxpc3Qgb2YgdW5pcXVlIGNvZGVwb2ludHMgd2UgYXJlIG1pc3NpbmdcbiAgICBjb2RlcG9pbnRzID0gdW5pcShjb2RlcG9pbnRzLCBnbHlwaHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dEZlYXR1cmVzOiB0ZXh0RmVhdHVyZXMsXG4gICAgICAgIGNvZGVwb2ludHM6IGNvZGVwb2ludHNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB1bmlxKGlkcywgYWxyZWFkeUhhdmUpIHtcbiAgICB2YXIgdSA9IFtdO1xuICAgIHZhciBsYXN0O1xuICAgIGlkcy5zb3J0KHNvcnROdW1iZXJzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaWRzW2ldICE9PSBsYXN0KSB7XG4gICAgICAgICAgICBsYXN0ID0gaWRzW2ldO1xuICAgICAgICAgICAgaWYgKCFhbHJlYWR5SGF2ZVtsYXN0XSkgdS5wdXNoKGlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHU7XG59XG5cbmZ1bmN0aW9uIHNvcnROdW1iZXJzKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNoYXBlVGV4dDogc2hhcGVUZXh0LFxuICAgIHNoYXBlSWNvbjogc2hhcGVJY29uXG59O1xuXG5cbi8vIFRoZSBwb3NpdGlvbiBvZiBhIGdseXBoIHJlbGF0aXZlIHRvIHRoZSB0ZXh0J3MgYW5jaG9yIHBvaW50LlxuZnVuY3Rpb24gUG9zaXRpb25lZEdseXBoKGNvZGVQb2ludCwgeCwgeSwgZ2x5cGgpIHtcbiAgICB0aGlzLmNvZGVQb2ludCA9IGNvZGVQb2ludDtcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG4gICAgdGhpcy5nbHlwaCA9IGdseXBoO1xufVxuXG4vLyBBIGNvbGxlY3Rpb24gb2YgcG9zaXRpb25lZCBnbHlwaHMgYW5kIHNvbWUgbWV0YWRhdGFcbmZ1bmN0aW9uIFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5wb3NpdGlvbmVkR2x5cGhzID0gcG9zaXRpb25lZEdseXBocztcbiAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICB0aGlzLmJvdHRvbSA9IGJvdHRvbTtcbiAgICB0aGlzLmxlZnQgPSBsZWZ0O1xuICAgIHRoaXMucmlnaHQgPSByaWdodDtcbn1cblxuZnVuY3Rpb24gc2hhcGVUZXh0KHRleHQsIGdseXBocywgbWF4V2lkdGgsIGxpbmVIZWlnaHQsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSwgc3BhY2luZywgdHJhbnNsYXRlKSB7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IFtdO1xuICAgIHZhciBzaGFwaW5nID0gbmV3IFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdHJhbnNsYXRlWzFdLCB0cmFuc2xhdGVbMV0sIHRyYW5zbGF0ZVswXSwgdHJhbnNsYXRlWzBdKTtcblxuICAgIC8vIHRoZSB5IG9mZnNldCAqc2hvdWxkKiBiZSBwYXJ0IG9mIHRoZSBmb250IG1ldGFkYXRhXG4gICAgdmFyIHlPZmZzZXQgPSAtMTc7XG5cbiAgICB2YXIgeCA9IHRyYW5zbGF0ZVswXTtcbiAgICB2YXIgeSA9IHRyYW5zbGF0ZVsxXSArIHlPZmZzZXQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNvZGVQb2ludCA9IHRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgdmFyIGdseXBoID0gZ2x5cGhzW2NvZGVQb2ludF07XG5cbiAgICAgICAgaWYgKCFnbHlwaCkgY29udGludWU7XG5cbiAgICAgICAgcG9zaXRpb25lZEdseXBocy5wdXNoKG5ldyBQb3NpdGlvbmVkR2x5cGgoY29kZVBvaW50LCB4LCB5LCBnbHlwaCkpO1xuICAgICAgICB4ICs9IGdseXBoLmFkdmFuY2UgKyBzcGFjaW5nO1xuICAgIH1cblxuICAgIGlmICghcG9zaXRpb25lZEdseXBocy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSk7XG5cbiAgICByZXR1cm4gc2hhcGluZztcbn1cblxudmFyIGJyZWFrYWJsZSA9IHsgMzI6IHRydWUgfTsgLy8gQ3VycmVudGx5IG9ubHkgYnJlYWtzIGF0IHJlZ3VsYXIgc3BhY2VzXG5cbmZ1bmN0aW9uIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSkge1xuICAgIHZhciBsYXN0U2FmZUJyZWFrID0gbnVsbDtcblxuICAgIHZhciBsZW5ndGhCZWZvcmVDdXJyZW50TGluZSA9IDA7XG4gICAgdmFyIGxpbmVTdGFydEluZGV4ID0gMDtcbiAgICB2YXIgbGluZSA9IDA7XG5cbiAgICB2YXIgbWF4TGluZUxlbmd0aCA9IDA7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IHNoYXBpbmcucG9zaXRpb25lZEdseXBocztcblxuICAgIGlmIChtYXhXaWR0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9uZWRHbHlwaHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2ldO1xuXG4gICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGgueCAtPSBsZW5ndGhCZWZvcmVDdXJyZW50TGluZTtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRHbHlwaC55ICs9IGxpbmVIZWlnaHQgKiBsaW5lO1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb25lZEdseXBoLnggPiBtYXhXaWR0aCAmJiBsYXN0U2FmZUJyZWFrICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGluZUxlbmd0aCA9IHBvc2l0aW9uZWRHbHlwaHNbbGFzdFNhZmVCcmVhayArIDFdLng7XG4gICAgICAgICAgICAgICAgbWF4TGluZUxlbmd0aCA9IE1hdGgubWF4KGxpbmVMZW5ndGgsIG1heExpbmVMZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IGxhc3RTYWZlQnJlYWsgKyAxOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGhzW2tdLnkgKz0gbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25lZEdseXBoc1trXS54IC09IGxpbmVMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGp1c3RpZnkpIHtcbiAgICAgICAgICAgICAgICAgICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgbGFzdFNhZmVCcmVhayAtIDEsIGp1c3RpZnkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxpbmVTdGFydEluZGV4ID0gbGFzdFNhZmVCcmVhayArIDE7XG4gICAgICAgICAgICAgICAgbGFzdFNhZmVCcmVhayA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGVuZ3RoQmVmb3JlQ3VycmVudExpbmUgKz0gbGluZUxlbmd0aDtcbiAgICAgICAgICAgICAgICBsaW5lKys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChicmVha2FibGVbcG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0pIHtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYXN0UG9zaXRpb25lZEdseXBoID0gcG9zaXRpb25lZEdseXBoc1twb3NpdGlvbmVkR2x5cGhzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBsYXN0TGluZUxlbmd0aCA9IGxhc3RQb3NpdGlvbmVkR2x5cGgueCArIGdseXBoc1tsYXN0UG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0uYWR2YW5jZTtcbiAgICBtYXhMaW5lTGVuZ3RoID0gTWF0aC5tYXgobWF4TGluZUxlbmd0aCwgbGFzdExpbmVMZW5ndGgpO1xuXG4gICAgdmFyIGhlaWdodCA9IChsaW5lICsgMSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgcG9zaXRpb25lZEdseXBocy5sZW5ndGggLSAxLCBqdXN0aWZ5KTtcbiAgICBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBib3VuZGluZyBib3hcbiAgICBzaGFwaW5nLnRvcCArPSAtdmVydGljYWxBbGlnbiAqIGhlaWdodDtcbiAgICBzaGFwaW5nLmJvdHRvbSA9IHNoYXBpbmcudG9wICsgaGVpZ2h0O1xuICAgIHNoYXBpbmcubGVmdCArPSAtaG9yaXpvbnRhbEFsaWduICogbWF4TGluZUxlbmd0aDtcbiAgICBzaGFwaW5nLnJpZ2h0ID0gc2hhcGluZy5sZWZ0ICsgbWF4TGluZUxlbmd0aDtcbn1cblxuZnVuY3Rpb24ganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBzdGFydCwgZW5kLCBqdXN0aWZ5KSB7XG4gICAgdmFyIGxhc3RBZHZhbmNlID0gZ2x5cGhzW3Bvc2l0aW9uZWRHbHlwaHNbZW5kXS5jb2RlUG9pbnRdLmFkdmFuY2U7XG4gICAgdmFyIGxpbmVJbmRlbnQgPSAocG9zaXRpb25lZEdseXBoc1tlbmRdLnggKyBsYXN0QWR2YW5jZSkgKiBqdXN0aWZ5O1xuXG4gICAgZm9yICh2YXIgaiA9IHN0YXJ0OyBqIDw9IGVuZDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCAtPSBsaW5lSW5kZW50O1xuICAgIH1cblxufVxuXG5mdW5jdGlvbiBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpIHtcbiAgICB2YXIgc2hpZnRYID0gKGp1c3RpZnkgLSBob3Jpem9udGFsQWxpZ24pICogbWF4TGluZUxlbmd0aDtcbiAgICB2YXIgc2hpZnRZID0gKC12ZXJ0aWNhbEFsaWduICogKGxpbmUgKyAxKSArIDAuNSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCArPSBzaGlmdFg7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueSArPSBzaGlmdFk7XG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIHNoYXBlSWNvbihpbWFnZSwgbGF5b3V0KSB7XG4gICAgaWYgKCFpbWFnZSB8fCAhaW1hZ2UucmVjdCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZHggPSBsYXlvdXRbJ2ljb24tb2Zmc2V0J11bMF07XG4gICAgdmFyIGR5ID0gbGF5b3V0WydpY29uLW9mZnNldCddWzFdO1xuICAgIHZhciB4MSA9IGR4IC0gaW1hZ2Uud2lkdGggLyAyO1xuICAgIHZhciB4MiA9IHgxICsgaW1hZ2Uud2lkdGg7XG4gICAgdmFyIHkxID0gZHkgLSBpbWFnZS5oZWlnaHQgLyAyO1xuICAgIHZhciB5MiA9IHkxICsgaW1hZ2UuaGVpZ2h0O1xuXG4gICAgcmV0dXJuIG5ldyBQb3NpdGlvbmVkSWNvbihpbWFnZSwgeTEsIHkyLCB4MSwgeDIpO1xufVxuXG5mdW5jdGlvbiBQb3NpdGlvbmVkSWNvbihpbWFnZSwgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgIHRoaXMudG9wID0gdG9wO1xuICAgIHRoaXMuYm90dG9tID0gYm90dG9tO1xuICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmluUGFjayA9IHJlcXVpcmUoJy4vYmluX3BhY2snKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTcHJpdGVBdGxhcztcbmZ1bmN0aW9uIFNwcml0ZUF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW1hZ2VzID0ge307XG4gICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0dXJlID0gMDsgLy8gV2ViR0wgSURcbiAgICB0aGlzLmZpbHRlciA9IDA7IC8vIFdlYkdMIElEXG4gICAgdGhpcy5waXhlbFJhdGlvID0gMTtcbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcbn1cblxuU3ByaXRlQXRsYXMucHJvdG90eXBlID0ge1xuICAgIGdldCBkZWJ1ZygpIHtcbiAgICAgICAgcmV0dXJuICdjYW52YXMnIGluIHRoaXM7XG4gICAgfSxcbiAgICBzZXQgZGVidWcodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKG5ld1JhdGlvKSB7XG4gICAgaWYgKHRoaXMucGl4ZWxSYXRpbyA9PT0gbmV3UmF0aW8pIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBvbGRSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbztcbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBuZXdSYXRpbztcblxuICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGggKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLmRhdGE7XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIG9sZFdpZHRoID0gdGhpcy53aWR0aCAqIG9sZFJhdGlvO1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBvbGRSYXRpbztcbiAgICAgICAgdmFyIG5ld1dpZHRoID0gdGhpcy53aWR0aCAqIG5ld1JhdGlvO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBuZXdSYXRpbztcblxuICAgICAgICAvLyBCYXNpYyBpbWFnZSBzY2FsaW5nLiBUT0RPOiBSZXBsYWNlIHRoaXMgd2l0aCBiZXR0ZXIgaW1hZ2Ugc2NhbGluZy5cbiAgICAgICAgdmFyIG5ld0ltYWdlID0gdGhpcy5kYXRhO1xuICAgICAgICB2YXIgb2xkSW1hZ2UgPSBvbGREYXRhO1xuXG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgbmV3SGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgIHZhciBvbGRZT2Zmc2V0ID0gTWF0aC5mbG9vcigoeSAqIG9sZEhlaWdodCkgLyBuZXdIZWlnaHQpICogb2xkV2lkdGg7XG4gICAgICAgICAgICB2YXIgbmV3WU9mZnNldCA9IHkgKiBuZXdXaWR0aDtcbiAgICAgICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgbmV3V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIHZhciBvbGRYID0gTWF0aC5mbG9vcigoeCAqIG9sZFdpZHRoKSAvIG5ld1dpZHRoKTtcbiAgICAgICAgICAgICAgICBuZXdJbWFnZVtuZXdZT2Zmc2V0ICsgeF0gPSBvbGRJbWFnZVtvbGRZT2Zmc2V0ICsgb2xkWF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvbGREYXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXJ0eSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGlydHk7XG59O1xuXG5mdW5jdGlvbiBjb3B5Qml0bWFwKHNyYywgc3JjU3RyaWRlLCBzcmNYLCBzcmNZLCBkc3QsIGRzdFN0cmlkZSwgZHN0WCwgZHN0WSwgd2lkdGgsIGhlaWdodCwgd3JhcCkge1xuICAgIHZhciBzcmNJID0gc3JjWSAqIHNyY1N0cmlkZSArIHNyY1g7XG4gICAgdmFyIGRzdEkgPSBkc3RZICogZHN0U3RyaWRlICsgZHN0WDtcbiAgICB2YXIgeCwgeTtcblxuICAgIGlmICh3cmFwKSB7XG4gICAgICAgIC8vIGFkZCAxIHBpeGVsIHdyYXBwZWQgcGFkZGluZyBvbiBlYWNoIHNpZGUgb2YgdGhlIGltYWdlXG4gICAgICAgIGRzdEkgLT0gZHN0U3RyaWRlO1xuICAgICAgICBmb3IgKHkgPSAtMTsgeSA8PSBoZWlnaHQ7IHkrKywgc3JjSSA9ICgoeSArIGhlaWdodCkgJSBoZWlnaHQgKyBzcmNZKSAqIHNyY1N0cmlkZSArIHNyY1gsIGRzdEkgKz0gZHN0U3RyaWRlKSB7XG4gICAgICAgICAgICBmb3IgKHggPSAtMTsgeCA8PSB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgKCh4ICsgd2lkdGgpICUgd2lkdGgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrLCBzcmNJICs9IHNyY1N0cmlkZSwgZHN0SSArPSBkc3RTdHJpZGUpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgeF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZUltYWdlID0gZnVuY3Rpb24ocGl4ZWxXaWR0aCwgcGl4ZWxIZWlnaHQpIHtcblxuICAgIC8vIEluY3JlYXNlIHRvIG5leHQgbnVtYmVyIGRpdmlzaWJsZSBieSA0LCBidXQgYXQgbGVhc3QgMS5cbiAgICAvLyBUaGlzIGlzIHNvIHdlIGNhbiBzY2FsZSBkb3duIHRoZSB0ZXh0dXJlIGNvb3JkaW5hdGVzIGFuZCBwYWNrIHRoZW1cbiAgICAvLyBpbnRvIDIgYnl0ZXMgcmF0aGVyIHRoYW4gNCBieXRlcy5cbiAgICAvLyBQYWQgaWNvbnMgdG8gcHJldmVudCB0aGVtIGZyb20gcG9sbHV0aW5nIG5laWdoYm91cnMgZHVyaW5nIGxpbmVhciBpbnRlcnBvbGF0aW9uXG4gICAgdmFyIHBhZGRpbmcgPSAyO1xuICAgIHZhciBwYWNrV2lkdGggPSBwaXhlbFdpZHRoICsgcGFkZGluZyArICg0IC0gKHBpeGVsV2lkdGggKyBwYWRkaW5nKSAlIDQpO1xuICAgIHZhciBwYWNrSGVpZ2h0ID0gcGl4ZWxIZWlnaHQgKyBwYWRkaW5nICsgKDQgLSAocGl4ZWxIZWlnaHQgKyBwYWRkaW5nKSAlIDQpOy8vICsgNDtcblxuICAgIC8vIFdlIGhhdmUgdG8gYWxsb2NhdGUgYSBuZXcgYXJlYSBpbiB0aGUgYmluLCBhbmQgc3RvcmUgYW4gZW1wdHkgaW1hZ2UgaW4gaXQuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHJlY3QgPSB0aGlzLmJpbi5hbGxvY2F0ZShwYWNrV2lkdGgsIHBhY2tIZWlnaHQpO1xuICAgIGlmIChyZWN0LncgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgfVxuXG4gICAgcmVjdC5vcmlnaW5hbFdpZHRoID0gcGl4ZWxXaWR0aDtcbiAgICByZWN0Lm9yaWdpbmFsSGVpZ2h0ID0gcGl4ZWxIZWlnaHQ7XG5cbiAgICByZXR1cm4gcmVjdDtcbn07XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uKG5hbWUsIHdyYXApIHtcbiAgICBpZiAodGhpcy5pbWFnZXNbbmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzW25hbWVdO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5zcHJpdGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHRoaXMuc3ByaXRlLmdldFNwcml0ZVBvc2l0aW9uKG5hbWUpO1xuICAgIGlmICghcG9zLndpZHRoIHx8ICFwb3MuaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciB3aWR0aCA9IHBvcy53aWR0aCAvIHBvcy5waXhlbFJhdGlvO1xuICAgIHZhciBoZWlnaHQgPSBwb3MuaGVpZ2h0IC8gcG9zLnBpeGVsUmF0aW87XG4gICAgdmFyIHJlY3QgPSB0aGlzLmFsbG9jYXRlSW1hZ2Uod2lkdGgsIGhlaWdodCk7XG4gICAgaWYgKHJlY3QudyA9PT0gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBuZXcgQXRsYXNJbWFnZShyZWN0LCB3aWR0aCwgaGVpZ2h0LCBwb3Muc2RmKTtcbiAgICB0aGlzLmltYWdlc1tuYW1lXSA9IGltYWdlO1xuXG4gICAgdGhpcy5jb3B5KHJlY3QsIHBvcywgd3JhcCk7XG5cbiAgICByZXR1cm4gaW1hZ2U7XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKG5hbWUsIHJlcGVhdGluZykge1xuICAgIHZhciBpbWFnZSA9IHRoaXMuZ2V0SW1hZ2UobmFtZSwgcmVwZWF0aW5nKTtcbiAgICB2YXIgcmVjdCA9IGltYWdlICYmIGltYWdlLnJlY3Q7XG5cbiAgICBpZiAoIXJlY3QpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB0aGUgaW1hZ2UgaXMgcmVwZWF0aW5nLCBnZXQgdGhlIGNvcnJlY3QgcG9zaXRpb24gb2YgdGhlIGltYWdlLCByYXRoZXIgdGhhbiB0aGVcbiAgICAvLyBvbmUgcm91bmRlZCB1cCB0byA0IHBpeGVscy5cbiAgICB2YXIgd2lkdGggPSByZXBlYXRpbmcgPyBpbWFnZS53aWR0aCA6IHJlY3QudztcbiAgICB2YXIgaGVpZ2h0ID0gcmVwZWF0aW5nID8gaW1hZ2UuaGVpZ2h0IDogcmVjdC5oO1xuICAgIHZhciBwYWRkaW5nID0gMTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNpemU6IFt3aWR0aCwgaGVpZ2h0XSxcbiAgICAgICAgdGw6IFsocmVjdC54ICsgcGFkZGluZykgICAgICAgICAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nKSAgICAgICAgICAvIHRoaXMuaGVpZ2h0XSxcbiAgICAgICAgYnI6IFsocmVjdC54ICsgcGFkZGluZyArIHdpZHRoKSAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nICsgaGVpZ2h0KSAvIHRoaXMuaGVpZ2h0XVxuICAgIH07XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5kYXRhKSB7XG4gICAgICAgIHZhciB3ID0gTWF0aC5mbG9vcih0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdmFyIGggPSBNYXRoLmZsb29yKHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQzMkFycmF5KHcgKiBoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24oZHN0LCBzcmMsIHdyYXApIHtcbiAgICAvLyBpZiAoIXNwcml0ZS0+cmFzdGVyKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnNwcml0ZS5pbWcuZGF0YSkgcmV0dXJuO1xuICAgIHZhciBzcmNJbWcgPSBuZXcgVWludDMyQXJyYXkodGhpcy5zcHJpdGUuaW1nLmRhdGEuYnVmZmVyKTtcblxuICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICB2YXIgZHN0SW1nID0gdGhpcy5kYXRhO1xuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuXG4gICAgY29weUJpdG1hcChcbiAgICAgICAgLyogc291cmNlIGJ1ZmZlciAqLyAgc3JjSW1nLFxuICAgICAgICAvKiBzb3VyY2Ugc3RyaWRlICovICB0aGlzLnNwcml0ZS5pbWcud2lkdGgsXG4gICAgICAgIC8qIHNvdXJjZSB4ICovICAgICAgIHNyYy54LFxuICAgICAgICAvKiBzb3VyY2UgeSAqLyAgICAgICBzcmMueSxcbiAgICAgICAgLyogZGVzdCBidWZmZXIgKi8gICAgZHN0SW1nLFxuICAgICAgICAvKiBkZXN0IHN0cmlkZSAqLyAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLFxuICAgICAgICAvKiBkZXN0IHggKi8gICAgICAgICAoZHN0LnggKyBwYWRkaW5nKSAqIHRoaXMucGl4ZWxSYXRpbyxcbiAgICAgICAgLyogZGVzdCB5ICovICAgICAgICAgKGRzdC55ICsgcGFkZGluZykgKiB0aGlzLnBpeGVsUmF0aW8sXG4gICAgICAgIC8qIGljb24gZGltZW5zaW9uICovIHNyYy53aWR0aCxcbiAgICAgICAgLyogaWNvbiBkaW1lbnNpb24gKi8gc3JjLmhlaWdodCxcbiAgICAgICAgLyogd3JhcCAqLyB3cmFwXG4gICAgKTtcblxuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLmFkZEljb25zID0gZnVuY3Rpb24oaWNvbnMsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpY29ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmdldEltYWdlKGljb25zW2ldKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCB0aGlzLmltYWdlcyk7XG59O1xuXG5TcHJpdGVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsLCBsaW5lYXIpIHtcbiAgICB2YXIgZmlyc3QgPSBmYWxzZTtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZmlyc3QgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgfVxuXG4gICAgdmFyIGZpbHRlclZhbCA9IGxpbmVhciA/IGdsLkxJTkVBUiA6IGdsLk5FQVJFU1Q7XG4gICAgaWYgKGZpbHRlclZhbCAhPT0gdGhpcy5maWx0ZXIpIHtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGZpbHRlclZhbCk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBmaWx0ZXJWYWwpO1xuICAgICAgICB0aGlzLmZpbHRlciA9IGZpbHRlclZhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kaXJ0eSkge1xuICAgICAgICB0aGlzLmFsbG9jYXRlKCk7XG5cbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIGdsLlRFWFRVUkVfMkQsIC8vIGVudW0gdGFyZ2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW5kIGxldmVsXG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gaW5kIGludGVybmFsZm9ybWF0XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgLy8gR0xzaXplaSB3aWR0aFxuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvLCAvLyBHTHNpemVpIGhlaWdodFxuICAgICAgICAgICAgICAgIDAsIC8vIGluZCBib3JkZXJcbiAgICAgICAgICAgICAgICBnbC5SR0JBLCAvLyBlbnVtIGZvcm1hdFxuICAgICAgICAgICAgICAgIGdsLlVOU0lHTkVEX0JZVEUsIC8vIGVudW0gdHlwZVxuICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KHRoaXMuZGF0YS5idWZmZXIpIC8vIE9iamVjdCBkYXRhXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChcbiAgICAgICAgICAgICAgICBnbC5URVhUVVJFXzJELCAvLyBlbnVtIHRhcmdldFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCBsZXZlbFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCB4b2Zmc2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW50IHlvZmZzZXRcbiAgICAgICAgICAgICAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLCAvLyBsb25nIHdpZHRoXG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8sIC8vIGxvbmcgaGVpZ2h0XG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gZW51bSBmb3JtYXRcbiAgICAgICAgICAgICAgICBnbC5VTlNJR05FRF9CWVRFLCAvLyBlbnVtIHR5cGVcbiAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheSh0aGlzLmRhdGEuYnVmZmVyKSAvLyBPYmplY3QgcGl4ZWxzXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuXG4gICAgICAgIC8vIERFQlVHXG4gICAgICAgIGlmICh0aGlzLmN0eCkge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmN0eC5nZXRJbWFnZURhdGEoMCwgMCwgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8pO1xuICAgICAgICAgICAgZGF0YS5kYXRhLnNldChuZXcgVWludDhDbGFtcGVkQXJyYXkodGhpcy5kYXRhLmJ1ZmZlcikpO1xuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54ICogdGhpcy5waXhlbFJhdGlvLCBmcmVlLnkgKiB0aGlzLnBpeGVsUmF0aW8sIGZyZWUudyAqIHRoaXMucGl4ZWxSYXRpbywgZnJlZS5oICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBBdGxhc0ltYWdlKHJlY3QsIHdpZHRoLCBoZWlnaHQsIHNkZikge1xuICAgIHRoaXMucmVjdCA9IHJlY3Q7XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuc2RmID0gc2RmO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBMYXRMbmcgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZycpO1xudmFyIExhdExuZ0JvdW5kcyA9IHJlcXVpcmUoJy4uL2dlby9sYXRfbG5nX2JvdW5kcycpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYW1lcmFPcHRpb25zXG4gKiBAcHJvcGVydHkge0FycmF5fSBbY2VudGVyXSBMYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIChwYXNzZWQgYXMgYFtsYXQsIGxuZ11gKVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6b29tXSBNYXAgem9vbSBsZXZlbFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtiZWFyaW5nXSBNYXAgcm90YXRpb24gYmVhcmluZyBpbiBkZWdyZWVzIGNvdW50ZXItY2xvY2t3aXNlIGZyb20gbm9ydGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcGl0Y2hdIFRoZSBhbmdsZSBhdCB3aGljaCB0aGUgY2FtZXJhIGlzIGxvb2tpbmcgYXQgdGhlIGdyb3VuZFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gW0FuaW1hdGlvbk9wdGlvbnNdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTUwMF0gTnVtYmVyIGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gW2Vhc2luZ11cbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IFtvZmZzZXQ9WzAsMF1dIHBvaW50LCBvcmlnaW4gb2YgbW92ZW1lbnQgcmVsYXRpdmUgdG8gbWFwIGNlbnRlclxuICogQHByb3BlcnR5IHtib29sZWFufSBbYW5pbWF0ZT10cnVlXSBXaGVuIHNldCB0byBmYWxzZSwgbm8gYW5pbWF0aW9uIGhhcHBlbnNcbiAqL1xuXG52YXIgQ2FtZXJhID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHt9O1xuXG51dGlsLmV4dGVuZChDYW1lcmEucHJvdG90eXBlLCAvKiogQGxlbmRzIE1hcC5wcm90b3R5cGUgKi97XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IHZpZXcgZ2VvZ3JhcGhpY2FsIHBvaW50LlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmNlbnRlcjsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgbG9jYXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjZW50ZXIgTGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSAocGFzc2VkIGFzIGBbbGF0LCBsbmddYClcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5zZXRDZW50ZXIoWy03NCwgMzhdKTtcbiAgICAgKi9cbiAgICBzZXRDZW50ZXI6IGZ1bmN0aW9uKGNlbnRlcikge1xuICAgICAgICB0aGlzLmp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUGFuIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgcGl4ZWxzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvZmZzZXQgW3gsIHldXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHBhbkJ5OiBmdW5jdGlvbihvZmZzZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5wYW5Ubyh0aGlzLnRyYW5zZm9ybS5jZW50ZXIsIHV0aWwuZXh0ZW5kKHtvZmZzZXQ6IFBvaW50LmNvbnZlcnQob2Zmc2V0KS5tdWx0KC0xKX0sIG9wdGlvbnMpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFBhbiB0byBhIGNlcnRhaW4gbG9jYXRpb24gd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBsYXRsbmcgYSBgTGF0TG5nYCBvYmplY3RcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcGFuVG86IGZ1bmN0aW9uKGxhdGxuZywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLnN0b3AoKTtcblxuICAgICAgICBsYXRsbmcgPSBMYXRMbmcuY29udmVydChsYXRsbmcpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2UsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLnJvdGF0ZSgtdHIuYW5nbGUpLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldCk7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSB0ci51bnByb2plY3QoZnJvbS5hZGQodG8uc3ViKGZyb20pLm11bHQoaykpKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgem9vbVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnRyYW5zZm9ybS56b29tOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIG1hcCB6b29tLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3pvb206IHpvb219KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBNYXAgem9vbSBsZXZlbFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gem9vbSB0aGUgbWFwIHRvIDVcbiAgICAgKiBtYXAuc2V0Wm9vbSg1KTtcbiAgICAgKi9cbiAgICBzZXRab29tOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHt6b29tOiB6b29tfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRvIGEgY2VydGFpbiB6b29tIGxldmVsIHdpdGggZWFzaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbVRvOiBmdW5jdGlvbih6b29tLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIG9wdGlvbnMuZWFzaW5nID0gdGhpcy5fdXBkYXRlRWFzaW5nKG9wdGlvbnMuZHVyYXRpb24sIHpvb20sIG9wdGlvbnMuZWFzaW5nKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLmNlbnRlcixcbiAgICAgICAgICAgIHN0YXJ0Wm9vbSA9IHRyLnpvb207XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkgb3B0aW9ucy5kdXJhdGlvbiA9IDA7XG5cbiAgICAgICAgaWYgKCF0aGlzLnpvb21pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRab29tQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0Wm9vbSwgem9vbSwgayksIGFyb3VuZCk7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmUnKS5maXJlKCd6b29tJyk7XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5lYXNlID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmR1cmF0aW9uID49IDIwMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5kdXJhdGlvbiA8IDIwMCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX29uWm9vbUVuZCk7XG4gICAgICAgICAgICB0aGlzLl9vblpvb21FbmQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCAyMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb20gaW4gYnkgMSBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHpvb21JbjogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSArIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIG91dCBieSAxIGxldmVsXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbU91dDogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSAtIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBiZWFyaW5nIGluIGRlZ3JlZXNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldEJlYXJpbmc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0uYmVhcmluZzsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgcm90YXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7YmVhcmluZzogYmVhcmluZ30pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiZWFyaW5nIE1hcCByb3RhdGlvbiBiZWFyaW5nIGluIGRlZ3JlZXMgY291bnRlci1jbG9ja3dpc2UgZnJvbSBub3J0aFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gcm90YXRlIHRoZSBtYXAgdG8gOTAgZGVncmVlc1xuICAgICAqIG1hcC5zZXRCZWFyaW5nKDkwKTtcbiAgICAgKi9cbiAgICBzZXRCZWFyaW5nOiBmdW5jdGlvbihiZWFyaW5nKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHtiZWFyaW5nOiBiZWFyaW5nfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSBiZWFyaW5nIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgZGVncmVlcyB3aXRoIGVhc2luZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGJlYXJpbmdcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcm90YXRlVG86IGZ1bmN0aW9uKGJlYXJpbmcsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBlYXNpbmc6IHV0aWwuZWFzZVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5nZXRCZWFyaW5nKCksXG4gICAgICAgICAgICBhcm91bmQgPSB0ci5jZW50ZXI7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBiZWFyaW5nID0gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhiZWFyaW5nLCBzdGFydCk7XG5cbiAgICAgICAgdGhpcy5yb3RhdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRCZWFyaW5nQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0LCBiZWFyaW5nLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtYXAgYmVhcmluZyB0byAwIChub3J0aCkgd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QW5pbWF0aW9uT3B0aW9uc31cbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICByZXNldE5vcnRoOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvdGF0ZVRvKDAsIHV0aWwuZXh0ZW5kKHtkdXJhdGlvbjogMTAwMH0sIG9wdGlvbnMpKTtcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgYW5nbGUgaW4gZGVncmVlc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0UGl0Y2g6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucGl0Y2g7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgbWFwIGFuZ2xlLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3BpdGNoOiBwaXRjaH0pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXRjaCBUaGUgYW5nbGUgYXQgd2hpY2ggdGhlIGNhbWVyYSBpcyBsb29raW5nIGF0IHRoZSBncm91bmRcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRQaXRjaDogZnVuY3Rpb24ocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8oe3BpdGNoOiBwaXRjaH0pO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIFpvb20gdG8gY29udGFpbiBjZXJ0YWluIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJvdW5kcyBbW21pbkxhdCwgbWluTG5nXSwgW21heExhdCwgbWF4TG5nXV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5zcGVlZD0xLjJdIEhvdyBmYXN0IGFuaW1hdGlvbiBvY2N1cnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuY3VydmU9MS40Ml0gSG93IG11Y2ggem9vbWluZyBvdXQgb2NjdXJzIGR1cmluZyBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmVhc2luZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLnBhZGRpbmcgaG93IG11Y2ggcGFkZGluZyB0aGVyZSBpcyBhcm91bmQgdGhlIGdpdmVuIGJvdW5kcyBvbiBlYWNoIHNpZGUgaW4gcGl4ZWxzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMubWF4Wm9vbVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIGZpdEJvdW5kczogZnVuY3Rpb24oYm91bmRzLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIG1heFpvb206IEluZmluaXR5XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIGJvdW5kcyA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KGJvdW5kcyk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLFxuICAgICAgICAgICAgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG53ID0gdHIucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxuICAgICAgICAgICAgc2UgPSB0ci5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSksXG4gICAgICAgICAgICBzaXplID0gc2Uuc3ViKG53KSxcbiAgICAgICAgICAgIHNjYWxlWCA9ICh0ci53aWR0aCAtIG9wdGlvbnMucGFkZGluZyAqIDIgLSBNYXRoLmFicyhvZmZzZXQueCkgKiAyKSAvIHNpemUueCxcbiAgICAgICAgICAgIHNjYWxlWSA9ICh0ci5oZWlnaHQgLSBvcHRpb25zLnBhZGRpbmcgKiAyIC0gTWF0aC5hYnMob2Zmc2V0LnkpICogMikgLyBzaXplLnk7XG5cbiAgICAgICAgb3B0aW9ucy5jZW50ZXIgPSB0ci51bnByb2plY3QobncuYWRkKHNlKS5kaXYoMikpO1xuICAgICAgICBvcHRpb25zLnpvb20gPSBNYXRoLm1pbih0ci5zY2FsZVpvb20odHIuc2NhbGUgKiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSkpLCBvcHRpb25zLm1heFpvb20pO1xuICAgICAgICBvcHRpb25zLmJlYXJpbmcgPSAwO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zLmxpbmVhciA/XG4gICAgICAgICAgICB0aGlzLmVhc2VUbyhvcHRpb25zKSA6XG4gICAgICAgICAgICB0aGlzLmZseVRvKG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgYW55IGNvbWJpbmF0aW9uIG9mIGNlbnRlciwgem9vbSwgYmVhcmluZywgYW5kIHBpdGNoLCB3aXRob3V0XG4gICAgICogYSB0cmFuc2l0aW9uLiBUaGUgbWFwIHdpbGwgcmV0YWluIHRoZSBjdXJyZW50IHZhbHVlcyBmb3IgYW55IG9wdGlvbnNcbiAgICAgKiBub3QgaW5jbHVkZWQgaW4gYG9wdGlvbnNgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBqdW1wVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICB6b29tQ2hhbmdlZCA9IGZhbHNlLFxuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSBmYWxzZSxcbiAgICAgICAgICAgIHBpdGNoQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICgnY2VudGVyJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3pvb20nIGluIG9wdGlvbnMgJiYgdHIuem9vbSAhPT0gK29wdGlvbnMuem9vbSkge1xuICAgICAgICAgICAgem9vbUNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuem9vbSA9ICtvcHRpb25zLnpvb207XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2JlYXJpbmcnIGluIG9wdGlvbnMgJiYgdHIuYmVhcmluZyAhPT0gK29wdGlvbnMuYmVhcmluZykge1xuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuYmVhcmluZyA9ICtvcHRpb25zLmJlYXJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3BpdGNoJyBpbiBvcHRpb25zICYmIHRyLnBpdGNoICE9PSArb3B0aW9ucy5waXRjaCkge1xuICAgICAgICAgICAgcGl0Y2hDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyLnBpdGNoID0gK29wdGlvbnMucGl0Y2g7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZScpO1xuXG4gICAgICAgIGlmICh6b29tQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5maXJlKCd6b29tJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYmVhcmluZ0NoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGl0Y2hDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3BpdGNoJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEVhc2luZyBhbmltYXRpb24gdG8gYSBzcGVjaWZpZWQgbG9jYXRpb24vem9vbS9iZWFyaW5nXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NhbWVyYU9wdGlvbnMrQW5pbWF0aW9uT3B0aW9uc30gb3B0aW9ucyBtYXAgdmlldyBhbmQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICBlYXNlVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdLFxuICAgICAgICAgICAgZHVyYXRpb246IDUwMCxcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkucm90YXRlKC10ci5hbmdsZSksXG4gICAgICAgICAgICBmcm9tID0gdHIucG9pbnQsXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgc3RhcnRQaXRjaCA9IHRoaXMuZ2V0UGl0Y2goKTtcblxuICAgICAgICB2YXIgem9vbSA9ICd6b29tJyBpbiBvcHRpb25zID8gK29wdGlvbnMuem9vbSA6IHN0YXJ0Wm9vbTtcbiAgICAgICAgdmFyIGJlYXJpbmcgPSAnYmVhcmluZycgaW4gb3B0aW9ucyA/IHRoaXMuX25vcm1hbGl6ZUJlYXJpbmcob3B0aW9ucy5iZWFyaW5nLCBzdGFydEJlYXJpbmcpIDogc3RhcnRCZWFyaW5nO1xuICAgICAgICB2YXIgcGl0Y2ggPSAncGl0Y2gnIGluIG9wdGlvbnMgPyArb3B0aW9ucy5waXRjaCA6IHN0YXJ0UGl0Y2g7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgdG8gPSAnY2VudGVyJyBpbiBvcHRpb25zID8gdHIucHJvamVjdChMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcikpLnN1YihvZmZzZXQuZGl2KHNjYWxlKSkgOiBmcm9tLFxuICAgICAgICAgICAgYXJvdW5kO1xuXG4gICAgICAgIGlmICh6b29tICE9PSBzdGFydFpvb20pIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKHRvLnN1Yihmcm9tKS5kaXYoMSAtIDEgLyBzY2FsZSkpKTtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgaWYgKHpvb20gIT09IHN0YXJ0Wm9vbSkge1xuICAgICAgICAgICAgICAgIHRyLnNldFpvb21Bcm91bmQoaW50ZXJwb2xhdGUoc3RhcnRab29tLCB6b29tLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHIuY2VudGVyID0gdHIudW5wcm9qZWN0KGZyb20uYWRkKHRvLnN1Yihmcm9tKS5tdWx0KGspKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBpdGNoICE9PSBzdGFydFBpdGNoKSB7XG4gICAgICAgICAgICAgICAgdHIucGl0Y2ggPSBpbnRlcnBvbGF0ZShzdGFydFBpdGNoLCBwaXRjaCwgayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICAgICAgaWYgKHRoaXMuem9vbWluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucm90YXRpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGbHlpbmcgYW5pbWF0aW9uIHRvIGEgc3BlY2lmaWVkIGxvY2F0aW9uL3pvb20vYmVhcmluZyB3aXRoIGF1dG9tYXRpYyBjdXJ2ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc3BlZWQ9MS4yXSBIb3cgZmFzdCBhbmltYXRpb24gb2NjdXJzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmN1cnZlPTEuNDJdIEhvdyBtdWNoIHpvb21pbmcgb3V0IG9jY3VycyBkdXJpbmcgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZWFzaW5nXVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gZmx5IHdpdGggZGVmYXVsdCBvcHRpb25zIHRvIG51bGwgaXNsYW5kXG4gICAgICogbWFwLmZseVRvKHtjZW50ZXI6IFswLCAwXSwgem9vbTogOX0pO1xuICAgICAqIC8vIHVzaW5nIGZseVRvIG9wdGlvbnNcbiAgICAgKiBtYXAuZmx5VG8oe1xuICAgICAqICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICogICB6b29tOiA5LFxuICAgICAqICAgc3BlZWQ6IDAuMixcbiAgICAgKiAgIGN1cnZlOiAxLFxuICAgICAqICAgZWFzaW5nOiBmdW5jdGlvbih0KSB7XG4gICAgICogICAgIHJldHVybiB0O1xuICAgICAqICAgfVxuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZseVRvOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIHNwZWVkOiAxLjIsXG4gICAgICAgICAgICBjdXJ2ZTogMS40MixcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpO1xuXG4gICAgICAgIHZhciBjZW50ZXIgPSAnY2VudGVyJyBpbiBvcHRpb25zID8gTGF0TG5nLmNvbnZlcnQob3B0aW9ucy5jZW50ZXIpIDogdGhpcy5nZXRDZW50ZXIoKTtcbiAgICAgICAgdmFyIHpvb20gPSAnem9vbScgaW4gb3B0aW9ucyA/ICArb3B0aW9ucy56b29tIDogc3RhcnRab29tO1xuICAgICAgICB2YXIgYmVhcmluZyA9ICdiZWFyaW5nJyBpbiBvcHRpb25zID8gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhvcHRpb25zLmJlYXJpbmcsIHN0YXJ0QmVhcmluZykgOiBzdGFydEJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGNlbnRlcikuc3ViKG9mZnNldC5kaXYoc2NhbGUpKTtcblxuICAgICAgICB2YXIgc3RhcnRXb3JsZFNpemUgPSB0ci53b3JsZFNpemUsXG4gICAgICAgICAgICByaG8gPSBvcHRpb25zLmN1cnZlLFxuICAgICAgICAgICAgViA9IG9wdGlvbnMuc3BlZWQsXG5cbiAgICAgICAgICAgIHcwID0gTWF0aC5tYXgodHIud2lkdGgsIHRyLmhlaWdodCksXG4gICAgICAgICAgICB3MSA9IHcwIC8gc2NhbGUsXG4gICAgICAgICAgICB1MSA9IHRvLnN1Yihmcm9tKS5tYWcoKSxcbiAgICAgICAgICAgIHJobzIgPSByaG8gKiByaG87XG5cbiAgICAgICAgZnVuY3Rpb24gcihpKSB7XG4gICAgICAgICAgICB2YXIgYiA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIChpID8gLTEgOiAxKSAqIHJobzIgKiByaG8yICogdTEgKiB1MSkgLyAoMiAqIChpID8gdzEgOiB3MCkgKiByaG8yICogdTEpO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubG9nKE1hdGguc3FydChiICogYiArIDEpIC0gYik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaW5oKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSAtIE1hdGguZXhwKC1uKSkgLyAyOyB9XG4gICAgICAgIGZ1bmN0aW9uIGNvc2gobikgeyByZXR1cm4gKE1hdGguZXhwKG4pICsgTWF0aC5leHAoLW4pKSAvIDI7IH1cbiAgICAgICAgZnVuY3Rpb24gdGFuaChuKSB7IHJldHVybiBzaW5oKG4pIC8gY29zaChuKTsgfVxuXG4gICAgICAgIHZhciByMCA9IHIoMCksXG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIChjb3NoKHIwKSAvIGNvc2gocjAgKyByaG8gKiBzKSk7IH0sXG4gICAgICAgICAgICB1ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHcwICogKChjb3NoKHIwKSAqIHRhbmgocjAgKyByaG8gKiBzKSAtIHNpbmgocjApKSAvIHJobzIpIC8gdTE7IH0sXG4gICAgICAgICAgICBTID0gKHIoMSkgLSByMCkgLyByaG87XG5cbiAgICAgICAgaWYgKE1hdGguYWJzKHUxKSA8IDAuMDAwMDAxKSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnModzAgLSB3MSkgPCAwLjAwMDAwMSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBrID0gdzEgPCB3MCA/IC0xIDogMTtcbiAgICAgICAgICAgIFMgPSBNYXRoLmFicyhNYXRoLmxvZyh3MSAvIHcwKSkgLyByaG87XG5cbiAgICAgICAgICAgIHUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gTWF0aC5leHAoayAqIHJobyAqIHMpOyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0aW9ucy5kdXJhdGlvbiA9IDEwMDAgKiBTIC8gVjtcblxuICAgICAgICB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuXG4gICAgICAgIHRoaXMuX2Vhc2UoZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgIHZhciBzID0gayAqIFMsXG4gICAgICAgICAgICAgICAgdXMgPSB1KHMpO1xuXG4gICAgICAgICAgICB0ci56b29tID0gc3RhcnRab29tICsgdHIuc2NhbGVab29tKDEgLyB3KHMpKTtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdCh1cykpLCBzdGFydFdvcmxkU2l6ZSk7XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgaWYgKGJlYXJpbmcgIT09IHN0YXJ0QmVhcmluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy56b29taW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGlzRWFzaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fYWJvcnRGbjtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU3RvcCBjdXJyZW50IGFuaW1hdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9hYm9ydEZuKSB7XG4gICAgICAgICAgICB0aGlzLl9hYm9ydEZuLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fYWJvcnRGbjtcblxuICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9maW5pc2hGbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2Vhc2U6IGZ1bmN0aW9uKGZyYW1lLCBmaW5pc2gsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoRm4gPSBmaW5pc2g7XG4gICAgICAgIHRoaXMuX2Fib3J0Rm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICBmcmFtZS5jYWxsKHRoaXMsIG9wdGlvbnMuZWFzaW5nKHQpKTtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2Fib3J0Rm47XG4gICAgICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5fZmluaXNoRm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgPyAwIDogb3B0aW9ucy5kdXJhdGlvbiwgdGhpcyk7XG4gICAgfSxcblxuICAgIC8vIGNvbnZlcnQgYmVhcmluZyBzbyB0aGF0IGl0J3MgbnVtZXJpY2FsbHkgY2xvc2UgdG8gdGhlIGN1cnJlbnQgb25lIHNvIHRoYXQgaXQgaW50ZXJwb2xhdGVzIHByb3Blcmx5XG4gICAgX25vcm1hbGl6ZUJlYXJpbmc6IGZ1bmN0aW9uKGJlYXJpbmcsIGN1cnJlbnRCZWFyaW5nKSB7XG4gICAgICAgIGJlYXJpbmcgPSB1dGlsLndyYXAoYmVhcmluZywgLTE4MCwgMTgwKTtcbiAgICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhiZWFyaW5nIC0gY3VycmVudEJlYXJpbmcpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyAtIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgLT0gMzYwO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyArIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgKz0gMzYwO1xuICAgICAgICByZXR1cm4gYmVhcmluZztcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUVhc2luZzogZnVuY3Rpb24oZHVyYXRpb24sIHpvb20sIGJlemllcikge1xuICAgICAgICB2YXIgZWFzaW5nO1xuXG4gICAgICAgIGlmICh0aGlzLmVhc2UpIHtcbiAgICAgICAgICAgIHZhciBlYXNlID0gdGhpcy5lYXNlLFxuICAgICAgICAgICAgICAgIHQgPSAoRGF0ZS5ub3coKSAtIGVhc2Uuc3RhcnQpIC8gZWFzZS5kdXJhdGlvbixcbiAgICAgICAgICAgICAgICBzcGVlZCA9IGVhc2UuZWFzaW5nKHQgKyAwLjAxKSAtIGVhc2UuZWFzaW5nKHQpLFxuXG4gICAgICAgICAgICAgICAgLy8gUXVpY2sgaGFjayB0byBtYWtlIG5ldyBiZXppZXIgdGhhdCBpcyBjb250aW51b3VzIHdpdGggbGFzdFxuICAgICAgICAgICAgICAgIHggPSAwLjI3IC8gTWF0aC5zcXJ0KHNwZWVkICogc3BlZWQgKyAwLjAwMDEpICogMC4wMSxcbiAgICAgICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KDAuMjcgKiAwLjI3IC0geCAqIHgpO1xuXG4gICAgICAgICAgICBlYXNpbmcgPSB1dGlsLmJlemllcih4LCB5LCAwLjI1LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyA9IGJlemllciA/IHV0aWwuYmV6aWVyLmFwcGx5KHV0aWwsIGJlemllcikgOiB1dGlsLmVhc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSBpbmZvcm1hdGlvbiBvbiBjdXJyZW50IGVhc2luZ1xuICAgICAgICB0aGlzLmVhc2UgPSB7XG4gICAgICAgICAgICBzdGFydDogKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcbiAgICAgICAgICAgIHRvOiBNYXRoLnBvdygyLCB6b29tKSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgIGVhc2luZzogZWFzaW5nXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGVhc2luZztcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBdHRyaWJ1dGlvbjtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2xcbiAqIEBjbGFzcyBBdHRyaWJ1dGlvblxuICogQGV4YW1wbGVcbiAqIG1hcC5hZGRDb250cm9sKG5ldyBtYXBib3hnbC5BdHRyaWJ1dGlvbigpKTtcbiAqL1xuZnVuY3Rpb24gQXR0cmlidXRpb24oKSB7fVxuXG5BdHRyaWJ1dGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICdib3R0b20tcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsLWF0dHJpYicsXG4gICAgICAgICAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBET00uY3JlYXRlKCdkaXYnLCBjbGFzc05hbWUsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmxvYWQnLCB0aGlzLl91cGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX3VwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgbWFwLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fdXBkYXRlLmJpbmQodGhpcykpO1xuICAgICAgICBtYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVFZGl0TGluay5iaW5kKHRoaXMpKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGF0dHJpYnV0aW9ucyA9IFtdO1xuXG4gICAgICAgIGlmICh0aGlzLl9tYXAuc3R5bGUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzW2lkXTtcbiAgICAgICAgICAgICAgICBpZiAoc291cmNlLmF0dHJpYnV0aW9uICYmIGF0dHJpYnV0aW9ucy5pbmRleE9mKHNvdXJjZS5hdHRyaWJ1dGlvbikgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9ucy5wdXNoKHNvdXJjZS5hdHRyaWJ1dGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY29udGFpbmVyLmlubmVySFRNTCA9IGF0dHJpYnV0aW9ucy5qb2luKCcgfCAnKTtcbiAgICAgICAgdGhpcy5fZWRpdExpbmsgPSB0aGlzLl9jb250YWluZXIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbWFwYm94LWltcHJvdmUtbWFwJylbMF07XG4gICAgICAgIHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVFZGl0TGluazogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9lZGl0TGluaykge1xuICAgICAgICAgICAgdmFyIGNlbnRlciA9IHRoaXMuX21hcC5nZXRDZW50ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX2VkaXRMaW5rLmhyZWYgPSAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXAtZmVlZGJhY2svIy8nICtcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyLmxuZyArICcvJyArIGNlbnRlci5sYXQgKyAnLycgKyBNYXRoLnJvdW5kKHRoaXMuX21hcC5nZXRab29tKCkgKyAxKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbnRyb2w7XG5cbi8qKlxuICogQSBiYXNlIGNsYXNzIGZvciBtYXAtcmVsYXRlZCBpbnRlcmZhY2UgZWxlbWVudHMuXG4gKlxuICogQGNsYXNzIENvbnRyb2xcbiAqL1xuZnVuY3Rpb24gQ29udHJvbCgpIHt9XG5cbkNvbnRyb2wucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIEFkZCB0aGlzIGNvbnRyb2wgdG8gdGhlIG1hcCwgcmV0dXJuaW5nIHRoZSBjb250cm9sIGl0c2VsZlxuICAgICAqIGZvciBjaGFpbmluZy4gVGhpcyB3aWxsIGluc2VydCB0aGUgY29udHJvbCdzIERPTSBlbGVtZW50IGludG9cbiAgICAgKiB0aGUgbWFwJ3MgRE9NIGVsZW1lbnQgaWYgdGhlIGNvbnRyb2wgaGFzIGEgYHBvc2l0aW9uYCBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbWFwXG4gICAgICogQHJldHVybnMge0NvbnRyb2x9IHRoaXNcbiAgICAgKi9cbiAgICBhZGRUbzogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMuX21hcCA9IG1hcDtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMucG9zaXRpb24pIHtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aGlzLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgICAgICB2YXIgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xuICAgICAgICAgICAgY29udGFpbmVyLmNsYXNzTmFtZSArPSAnIG1hcGJveGdsLWN0cmwnO1xuICAgICAgICAgICAgaWYgKHBvcy5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuaW5zZXJ0QmVmb3JlKGNvbnRhaW5lciwgY29ybmVyLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhpcyBjb250cm9sIGZyb20gdGhlIG1hcCBpdCBoYXMgYmVlbiBhZGRlZCB0by5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtDb250cm9sfSB0aGlzXG4gICAgICovXG4gICAgcmVtb3ZlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub25SZW1vdmUpIHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcbiAgICAgICAgdGhpcy5fbWFwID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOYXZpZ2F0aW9uO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuYXZpZ2F0aW9uIGNvbnRyb2wgd2l0aCB6b29tIGJ1dHRvbnMgYW5kIGEgY29tcGFzc1xuICogQGNsYXNzIE5hdmlnYXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wb3NpdGlvbj10b3AtcmlnaHRdIEEgc3RyaW5nIGluZGljYXRpbmcgdGhlIGNvbnRyb2wncyBwb3NpdGlvbiBvbiB0aGUgbWFwLiBPcHRpb25zIGFyZSBgdG9wLXJpZ2h0YCwgYHRvcC1sZWZ0YCwgYGJvdHRvbS1yaWdodGAsIGBib3R0b20tbGVmdGBcbiAqIEBleGFtcGxlXG4gKiBtYXAuYWRkQ29udHJvbChuZXcgbWFwYm94Z2wuTmF2aWdhdGlvbih7cG9zaXRpb246ICd0b3AtbGVmdCd9KSk7IC8vIHBvc2l0aW9uIGlzIG9wdGlvbmFsXG4gKi9cbmZ1bmN0aW9uIE5hdmlnYXRpb24ob3B0aW9ucykge1xuICAgIHV0aWwuc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbn1cblxuTmF2aWdhdGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICd0b3AtcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsJztcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgY2xhc3NOYW1lICsgJy1ncm91cCcsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fem9vbUluQnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLWluJywgbWFwLnpvb21Jbi5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLW91dCcsIG1hcC56b29tT3V0LmJpbmQobWFwKSk7XG4gICAgICAgIHRoaXMuX2NvbXBhc3MgPSB0aGlzLl9jcmVhdGVCdXR0b24oY2xhc3NOYW1lICsgJy1jb21wYXNzJywgbWFwLnJlc2V0Tm9ydGguYmluZChtYXApKTtcblxuICAgICAgICB2YXIgY29tcGFzc0NhbnZhcyA9IHRoaXMuX2NvbXBhc3NDYW52YXMgPSBET00uY3JlYXRlKCdjYW52YXMnLCBjbGFzc05hbWUgKyAnLWNvbXBhc3MtY2FudmFzJywgdGhpcy5fY29tcGFzcyk7XG4gICAgICAgIGNvbXBhc3NDYW52YXMuc3R5bGUuY3NzVGV4dCA9ICd3aWR0aDozMHB4OyBoZWlnaHQ6MzBweDsnO1xuICAgICAgICBjb21wYXNzQ2FudmFzLndpZHRoID0gMjYgKiAyO1xuICAgICAgICBjb21wYXNzQ2FudmFzLmhlaWdodCA9IDI2ICogMjtcblxuICAgICAgICB0aGlzLl9jb21wYXNzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uQ29tcGFzc0Rvd24uYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc01vdmUgPSB0aGlzLl9vbkNvbXBhc3NNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc1VwID0gdGhpcy5fb25Db21wYXNzVXAuYmluZCh0aGlzKTtcblxuICAgICAgICB0aGlzLl9jb21wYXNzQ3R4ID0gY29tcGFzc0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgIG1hcC5vbigncm90YXRlJywgdGhpcy5fZHJhd05vcnRoLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLl9kcmF3Tm9ydGgoKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfb25Db21wYXNzRG93bjogZnVuY3Rpb24oZSkge1xuICAgICAgICBET00uZGlzYWJsZURyYWcoKTtcblxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkNvbXBhc3NNb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQ29tcGFzc1VwKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG5cbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc01vdmU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLnNjcmVlblgsXG4gICAgICAgICAgICBkID0geCA8IDIgPyAtNSA6IC8vIGxlZnQgZWRnZSBvZiB0aGUgc2NyZWVuLCBjb250aW51ZSByb3RhdGluZ1xuICAgICAgICAgICAgICAgIHggPiB3aW5kb3cuc2NyZWVuLndpZHRoIC0gMiA/IDUgOiAvLyByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgKHggLSB0aGlzLl9wcmV2WCkgLyA0O1xuXG4gICAgICAgIHRoaXMuX21hcC5zZXRCZWFyaW5nKHRoaXMuX21hcC5nZXRCZWFyaW5nKCkgLSBkKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG4gICAgICAgIHRoaXMuX21vdmVkID0gdHJ1ZTtcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSxcblxuICAgIF9vbkNvbXBhc3NVcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQ29tcGFzc01vdmUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Db21wYXNzVXApO1xuICAgICAgICBET00uZW5hYmxlRHJhZygpO1xuXG4gICAgICAgIGlmICh0aGlzLl9tb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy5fbW92ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIERPTS5zdXBwcmVzc0NsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24oY2xhc3NOYW1lLCBmbikge1xuICAgICAgICB2YXIgYSA9IERPTS5jcmVhdGUoJ2J1dHRvbicsIGNsYXNzTmFtZSwgdGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkgeyBmbigpOyB9KTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfSxcblxuICAgIF9kcmF3Tm9ydGg6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmFkID0gMjAsXG4gICAgICAgICAgICB3aWR0aCA9IDgsXG4gICAgICAgICAgICBjZW50ZXIgPSAyNixcbiAgICAgICAgICAgIGFuZ2xlID0gdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSArIChNYXRoLlBJIC8gMiksXG4gICAgICAgICAgICBjdHggPSB0aGlzLl9jb21wYXNzQ3R4O1xuXG4gICAgICAgIHRoaXMuX2NvbXBhc3NDYW52YXMud2lkdGggPSB0aGlzLl9jb21wYXNzQ2FudmFzLndpZHRoO1xuXG4gICAgICAgIGN0eC50cmFuc2xhdGUoY2VudGVyLCBjZW50ZXIpO1xuICAgICAgICBjdHgucm90YXRlKGFuZ2xlKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnIzAwMCc7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbygtcmFkLCAwKTtcbiAgICAgICAgY3R4LmxpbmVUbygwLCB3aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gJyNiYmInO1xuICAgICAgICBjdHgubW92ZVRvKDAsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIHdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbyhyYWQsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSAnI2ZmZic7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSA0O1xuICAgICAgICBjdHgubW92ZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgd2lkdGgpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBJbnRlcmFjdGlvbiA9IHJlcXVpcmUoJy4vaW50ZXJhY3Rpb24nKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmdfYm91bmRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSGFuZGxlcnM7XG5cbmZ1bmN0aW9uIEhhbmRsZXJzKG1hcCkge1xuXG4gICAgdmFyIHJvdGF0ZUVuZDtcblxuICAgIHZhciBib3g7XG5cbiAgICB2YXIgaW5lcnRpYUxpbmVhcml0eSA9IDAuMixcbiAgICAgICAgaW5lcnRpYUVhc2luZyA9IHV0aWwuYmV6aWVyKDAsIDAsIGluZXJ0aWFMaW5lYXJpdHksIDEpO1xuXG4gICAgZnVuY3Rpb24gYm94em9vbUZpbmlzaCgpIHtcbiAgICAgICAgaWYgKGJveCkge1xuICAgICAgICAgICAgYm94LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoYm94KTtcbiAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgIGJveCA9IGZhbHNlO1xuICAgICAgICAgICAgRE9NLmVuYWJsZURyYWcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaW50ZXJhY3Rpb24gPSBuZXcgSW50ZXJhY3Rpb24obWFwLmdldENhbnZhcygpKVxuICAgICAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5sYXRMbmcgPSBtYXAudW5wcm9qZWN0KGUucG9pbnQpO1xuICAgICAgICAgICAgbWFwLmZpcmUoJ2NsaWNrJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZGJsY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnZGJsY2xpY2snLCBlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW91c2Vtb3ZlJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLnN0b3AoKTtcbiAgICAgICAgICAgIG1hcC5yZXNpemUoKTtcbiAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYgKGUuYWx0S2V5IHx8IGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHBhbiA9IDgwO1xuICAgICAgICAgICAgdmFyIHJvdGF0ZSA9IDI7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHpvb21CeSh6KSB7XG4gICAgICAgICAgICAgICAgbWFwLnpvb21UbyhNYXRoLnJvdW5kKG1hcC5nZXRab29tKCkpICsgKGUuc2hpZnRLZXkgPyAyIDogMSkgKiB6KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFuQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5wYW5CeSh2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcm90YXRlQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5zZXRCZWFyaW5nKG1hcC5nZXRCZWFyaW5nKCkgKyB2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDYxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTA3OlxuICAgICAgICAgICAgICAgIGNhc2UgMTcxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTg3OlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTg5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTA5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTczOlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoLTEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM3OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQnkoLXJvdGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5CeShbLXBhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzk6XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVCeShyb3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFuQnkoW3BhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzg6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCAtcGFuXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDA6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCBwYW5dKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIG1hcC5zdG9wKCk7XG4gICAgICAgICAgICB2YXIgbW91c2VMb2NhdGlvbiA9IG1hcC50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihlLnBvaW50LmFkZChlLm9mZnNldCkpO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5zZXRMb2NhdGlvbkF0UG9pbnQobW91c2VMb2NhdGlvbiwgZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbmVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5pbmVydGlhKSB7XG4gICAgICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29udmVydCB2ZWxvY2l0eSB0byBweC9zICYgYWRqdXN0IGZvciBpbmNyZWFzZWQgaW5pdGlhbCBhbmltYXRpb24gc3BlZWQgd2hlbiBlYXNpbmcgb3V0XG4gICAgICAgICAgICAgICAgdmFyIHZlbG9jaXR5ID0gZS5pbmVydGlhLm11bHQoMTAwMCAqIGluZXJ0aWFMaW5lYXJpdHkpLFxuICAgICAgICAgICAgICAgICAgICBzcGVlZCA9IHZlbG9jaXR5Lm1hZygpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heFNwZWVkID0gNDAwMDsgLy8gcHgvc1xuXG4gICAgICAgICAgICAgICAgaWYgKHNwZWVkID49IG1heFNwZWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwZWVkID0gbWF4U3BlZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZlbG9jaXR5Ll91bml0KCkuX211bHQobWF4U3BlZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBkZWNlbGVyYXRpb24gPSA4MDAwLCAvLyBweC9zXjJcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzcGVlZCAvIChkZWNlbGVyYXRpb24gKiBpbmVydGlhTGluZWFyaXR5KSxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gdmVsb2NpdHkubXVsdCgtZHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gICAgICAgICAgICAgICAgbWFwLnBhbkJ5KG9mZnNldCwge1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24gKiAxMDAwLFxuICAgICAgICAgICAgICAgICAgICBlYXNpbmc6IGluZXJ0aWFFYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIG5vTW92ZVN0YXJ0OiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignem9vbScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIFNjYWxlIGJ5IHNpZ21vaWQgb2Ygc2Nyb2xsIHdoZWVsIGRlbHRhLlxuICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAvICgxICsgTWF0aC5leHAoLU1hdGguYWJzKGUuZGVsdGEgLyAxMDApKSk7XG4gICAgICAgICAgICBpZiAoZS5kZWx0YSA8IDAgJiYgc2NhbGUgIT09IDApIHNjYWxlID0gMSAvIHNjYWxlO1xuXG4gICAgICAgICAgICB2YXIgZnJvbVNjYWxlID0gbWFwLmVhc2UgJiYgaXNGaW5pdGUoZS5kZWx0YSkgPyBtYXAuZWFzZS50byA6IG1hcC50cmFuc2Zvcm0uc2NhbGUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSAhaXNGaW5pdGUoZS5kZWx0YSkgPyA4MDAgOiAwO1xuXG4gICAgICAgICAgICBtYXAuem9vbVRvKG1hcC50cmFuc2Zvcm0uc2NhbGVab29tKGZyb21TY2FsZSAqIHNjYWxlKSwge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICBhcm91bmQ6IG1hcC51bnByb2plY3QoZS5wb2ludClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3JvdGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIHZhciBjZW50ZXIgPSBtYXAudHJhbnNmb3JtLmNlbnRlclBvaW50LCAvLyBDZW50ZXIgb2Ygcm90YXRpb25cbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyID0gZS5zdGFydC5zdWIoY2VudGVyKSxcbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyRGlzdCA9IHN0YXJ0VG9DZW50ZXIubWFnKCk7XG5cbiAgICAgICAgICAgIG1hcC5yb3RhdGluZyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBjbGljayB3YXMgdG9vIGNsb3NlIHRvIHRoZSBjZW50ZXIsIG1vdmUgdGhlIGNlbnRlciBvZiByb3RhdGlvbiBieSAyMDAgcGl4ZWxzXG4gICAgICAgICAgICAvLyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBjbGljay5cbiAgICAgICAgICAgIGlmIChzdGFydFRvQ2VudGVyRGlzdCA8IDIwMCkge1xuICAgICAgICAgICAgICAgIGNlbnRlciA9IGUuc3RhcnQuYWRkKG5ldyBQb2ludCgtMjAwLCAwKS5fcm90YXRlKHN0YXJ0VG9DZW50ZXIuYW5nbGUoKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYmVhcmluZ0RpZmYgPSBlLnByZXYuc3ViKGNlbnRlcikuYW5nbGVXaXRoKGUuY3VycmVudC5zdWIoY2VudGVyKSkgLyBNYXRoLlBJICogMTgwO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5iZWFyaW5nID0gbWFwLmdldEJlYXJpbmcoKSAtIGJlYXJpbmdEaWZmO1xuXG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHJvdGF0ZUVuZCk7XG4gICAgICAgICAgICByb3RhdGVFbmQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBtYXAucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBtYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgICAgICB9LCAyMDApO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2JveHpvb21zdGFydCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghYm94KSB7XG4gICAgICAgICAgICAgICAgYm94ID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWJveHpvb20nLCBtYXAuZ2V0Q29udGFpbmVyKCkpO1xuICAgICAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QuYWRkKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgICAgICBtYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gICAgICAgICAgICAgICAgRE9NLmRpc2FibGVEcmFnKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBtaW5YID0gTWF0aC5taW4oZS5zdGFydC54LCBlLmN1cnJlbnQueCk7XG4gICAgICAgICAgICB2YXIgbWF4WCA9IE1hdGgubWF4KGUuc3RhcnQueCwgZS5jdXJyZW50LngpO1xuICAgICAgICAgICAgdmFyIG1pblkgPSBNYXRoLm1pbihlLnN0YXJ0LnksIGUuY3VycmVudC55KTtcbiAgICAgICAgICAgIHZhciBtYXhZID0gTWF0aC5tYXgoZS5zdGFydC55LCBlLmN1cnJlbnQueSk7XG5cbiAgICAgICAgICAgIERPTS5zZXRUcmFuc2Zvcm0oYm94LCAndHJhbnNsYXRlKCcgKyBtaW5YICsgJ3B4LCcgKyBtaW5ZICsgJ3B4KScpO1xuICAgICAgICAgICAgYm94LnN0eWxlLndpZHRoID0gKG1heFggLSBtaW5YKSArICdweCc7XG4gICAgICAgICAgICBib3guc3R5bGUuaGVpZ2h0ID0gKG1heFkgLSBtaW5ZKSArICdweCc7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGJveHpvb21GaW5pc2goKTtcblxuICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICAgICAgbWFwLnVucHJvamVjdChlLnN0YXJ0KSxcbiAgICAgICAgICAgICAgICBtYXAudW5wcm9qZWN0KGUuY3VycmVudClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzLCB7IGxpbmVhcjogdHJ1ZSB9KS5maXJlKCdib3h6b29tZW5kJywge1xuICAgICAgICAgICAgICAgIGJveFpvb21Cb3VuZHM6IGJvdW5kc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWNhbmNlbCcsIGJveHpvb21GaW5pc2gpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogQWRkcyBwb3NpdGlvbmFsIGNvb3JkaW5hdGVzIHRvIFVSTCBoYXNoZXMuIFBhc3NlZCBhcyBhbiBvcHRpb24gdG8gdGhlIG1hcCBvYmplY3RcbiAqXG4gKiBAY2xhc3MgbWFwYm94Z2wuSGFzaFxuICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEhhc2g7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmZ1bmN0aW9uIEhhc2goKSB7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ19vbkhhc2hDaGFuZ2UnLFxuICAgICAgICAnX3VwZGF0ZUhhc2gnXG4gICAgXSwgdGhpcyk7XG59XG5cbkhhc2gucHJvdG90eXBlID0ge1xuICAgIC8qIE1hcCBlbGVtZW50IHRvIGxpc3RlbiBmb3IgY29vcmRpbmF0ZSBjaGFuZ2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwXG4gICAgICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVIYXNoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qIFJlbW92ZXMgaGFzaFxuICAgICAqXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlZW5kJywgdGhpcy5fdXBkYXRlSGFzaCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9tYXA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25IYXNoQ2hhbmdlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGxvYyA9IGxvY2F0aW9uLmhhc2gucmVwbGFjZSgnIycsICcnKS5zcGxpdCgnLycpO1xuICAgICAgICBpZiAobG9jLmxlbmd0aCA+PSAzKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAuanVtcFRvKHtcbiAgICAgICAgICAgICAgICBjZW50ZXI6IFsrbG9jWzFdLCArbG9jWzJdXSxcbiAgICAgICAgICAgICAgICB6b29tOiArbG9jWzBdLFxuICAgICAgICAgICAgICAgIGJlYXJpbmc6ICsobG9jWzNdIHx8IDApXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUhhc2g6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY2VudGVyID0gdGhpcy5fbWFwLmdldENlbnRlcigpLFxuICAgICAgICAgICAgem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCksXG4gICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5fbWFwLmdldEJlYXJpbmcoKSxcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IE1hdGgubWF4KDAsIE1hdGguY2VpbChNYXRoLmxvZyh6b29tKSAvIE1hdGguTE4yKSksXG5cbiAgICAgICAgICAgIGhhc2ggPSAnIycgKyAoTWF0aC5yb3VuZCh6b29tICogMTAwKSAvIDEwMCkgK1xuICAgICAgICAgICAgICAgICcvJyArIGNlbnRlci5sYXQudG9GaXhlZChwcmVjaXNpb24pICtcbiAgICAgICAgICAgICAgICAnLycgKyBjZW50ZXIubG5nLnRvRml4ZWQocHJlY2lzaW9uKSArXG4gICAgICAgICAgICAgICAgKGJlYXJpbmcgPyAnLycgKyAoTWF0aC5yb3VuZChiZWFyaW5nICogMTApIC8gMTApIDogJycpO1xuXG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSgnJywgJycsIGhhc2gpO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcmFjdGlvbjtcblxuLyoqXG4gKiBNb3VzZSBldmVudFxuICpcbiAqIEBldmVudCBNYXAjbW91c2Vtb3ZlXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtFdmVudH0gb3JpZ2luYWxFdmVudCB0aGUgb3JpZ2luYWwgRE9NIGV2ZW50XG4gKi9cblxuLyoqXG4gKiBEb3VibGUgY2xpY2sgZXZlbnQuXG4gKlxuICogQGV2ZW50IE1hcCNkYmxjbGlja1xuICogQHR5cGUge09iamVjdH1cbiAqIEBwcm9wZXJ0eSB7UG9pbnR9IHBvaW50IHRoZSBwaXhlbCBsb2NhdGlvbiBvZiB0aGUgZXZlbnRcbiAqL1xuXG4vKipcbiAqIFBhbiBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtQb2ludH0gb2Zmc2V0IGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBtb3ZlbWVudCBmcm9tIHRoZSBwcmV2aW91cyBtYXAgbG9jYXRpb24gdG8gdGhlIGN1cnJlbnQgb25lLlxuICovXG5cbi8qKlxuICogUGFuIGVuZCBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuZW5kXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlbG9jaXR5IGEgbWVhc3VyZSBvZiBob3cgbXVjaCBpbmVydGlhIHdhcyByZWNvcmRlZCBpbiB0aGlzIHBhbiBtb3Rpb25cbiAqL1xuXG5mdW5jdGlvbiBJbnRlcmFjdGlvbihlbCkge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHRoaXM7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuXG4gICAgdmFyIHJvdGF0aW5nID0gZmFsc2UsXG4gICAgICAgIHBhbm5lZCA9IGZhbHNlLFxuICAgICAgICBib3h6b29tID0gZmFsc2UsXG4gICAgICAgIGZpcnN0UG9zID0gbnVsbCxcbiAgICAgICAgcG9zID0gbnVsbCxcbiAgICAgICAgaW5lcnRpYSA9IG51bGwsXG4gICAgICAgIG5vdztcblxuICAgIGZ1bmN0aW9uIG1vdXNlUG9zKGUpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChcbiAgICAgICAgICAgIGUuY2xpZW50WCAtIHJlY3QubGVmdCAtIGVsLmNsaWVudExlZnQsXG4gICAgICAgICAgICBlLmNsaWVudFkgLSByZWN0LnRvcCAtIGVsLmNsaWVudFRvcCk7XG4gICAgfVxuXG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbihldikge1xuICAgICAgICByb3RhdGluZyA9IHRydWU7XG4gICAgICAgIGZpcnN0UG9zID0gcG9zID0gbW91c2VQb3MoZXYpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93biwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbm1vdXNldXAsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbm1vdXNlbW92ZSwgZmFsc2UpO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25jbGljaywgZmFsc2UpO1xuICAgIHNjcm9sbHdoZWVsKHpvb20pO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kb3VibGVjbGljaywgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUsIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywga2V5ZG93biwgZmFsc2UpO1xuXG4gICAgZnVuY3Rpb24gem9vbSh0eXBlLCBkZWx0YSwgcG9pbnQpIHtcbiAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnem9vbScsIHtcbiAgICAgICAgICAgIHNvdXJjZTogdHlwZSxcbiAgICAgICAgICAgIGRlbHRhOiBkZWx0YSxcbiAgICAgICAgICAgIHBvaW50OiBwb2ludFxuICAgICAgICB9KTtcbiAgICAgICAgaW5lcnRpYSA9IG51bGw7XG4gICAgICAgIG5vdyA9IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2NsaWNrJywge3BvaW50OiBwb2ludCwgb3JpZ2luYWxFdmVudDogZXZ9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3VzZW1vdmUocG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ21vdXNlbW92ZScsIHtwb2ludDogcG9pbnQsIG9yaWdpbmFsRXZlbnQ6IGV2fSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFuKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBwb3Muc3ViKHBvaW50KTtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3BhbicsIHtvZmZzZXQ6IG9mZnNldCwgcG9pbnQ6IHBvaW50fSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCBhbiBhdmVyYWdlZCB2ZXJzaW9uIG9mIHRoaXMgbW92ZW1lbnQgdG8gdGhlIGluZXJ0aWEgdmVjdG9yXG4gICAgICAgICAgICBpZiAoaW5lcnRpYSkge1xuICAgICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBub3c7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRpbWVzIGl0J3MgMCBhZnRlciBzb21lIGVycmF0aWMgcGFuaW5nXG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lID0gZHVyYXRpb24gKyBub3c7XG4gICAgICAgICAgICAgICAgICAgIGluZXJ0aWEucHVzaChbdGltZSwgcG9pbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGluZXJ0aWEubGVuZ3RoID4gMiAmJiB0aW1lIC0gaW5lcnRpYVswXVswXSA+IDEwMCkgaW5lcnRpYS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmVydGlhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgcG9zID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUoKSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3Jlc2l6ZScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtleWRvd24oZXYpIHtcbiAgICAgICAgaWYgKGJveHpvb20gJiYgZXYua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21jYW5jZWwnKTtcbiAgICAgICAgICAgIGJveHpvb20gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2tleWRvd24nLCBldik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcm90YXRlKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3JvdGF0ZScsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogZmlyc3RQb3MsXG4gICAgICAgICAgICAgICAgcHJldjogcG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IHBvaW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvcyA9IHBvaW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG91YmxlY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2RibGNsaWNrJywge1xuICAgICAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZWRvd24oZXYpIHtcbiAgICAgICAgZmlyc3RQb3MgPSBwb3MgPSBtb3VzZVBvcyhldik7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2Rvd24nKTtcbiAgICAgICAgaWYgKGV2LnNoaWZ0S2V5IHx8ICgoZXYud2hpY2ggPT09IDEpICYmIChldi5idXR0b24gPT09IDEpKSkge1xuICAgICAgICAgIGJveHpvb20gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZXVwKGV2KSB7XG4gICAgICAgIHBhbm5lZCA9IHBvcyAmJiBmaXJzdFBvcyAmJiAocG9zLnggIT09IGZpcnN0UG9zLnggfHwgcG9zLnkgIT09IGZpcnN0UG9zLnkpO1xuXG4gICAgICAgIHJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgIHBvcyA9IG51bGw7XG5cbiAgICAgICAgaWYgKGJveHpvb20pIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21lbmQnLCB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGZpcnN0UG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IG1vdXNlUG9zKGV2KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBib3h6b29tID0gZmFsc2U7XG5cbiAgICAgICAgfSBlbHNlIGlmIChpbmVydGlhICYmIGluZXJ0aWEubGVuZ3RoID49IDIgJiYgbm93ID4gRGF0ZS5ub3coKSAtIDEwMCkge1xuICAgICAgICAgICAgdmFyIGxhc3QgPSBpbmVydGlhW2luZXJ0aWEubGVuZ3RoIC0gMV0sXG4gICAgICAgICAgICAgICAgZmlyc3QgPSBpbmVydGlhWzBdLFxuICAgICAgICAgICAgICAgIHZlbG9jaXR5ID0gbGFzdFsxXS5zdWIoZmlyc3RbMV0pLmRpdihsYXN0WzBdIC0gZmlyc3RbMF0pO1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgncGFuZW5kJywge2luZXJ0aWE6IHZlbG9jaXR5fSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChwb3MpIHtcbiAgICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdwYW5lbmQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluZXJ0aWEgPSBudWxsO1xuICAgICAgICBub3cgPSBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubW91c2Vtb3ZlKGV2KSB7XG4gICAgICAgIHZhciBwb2ludCA9IG1vdXNlUG9zKGV2KTtcblxuICAgICAgICBpZiAoYm94em9vbSkge1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnYm94em9vbXN0YXJ0Jywge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBmaXJzdFBvcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50OiBwb2ludFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyb3RhdGluZykge1xuICAgICAgICAgICAgcm90YXRlKHBvaW50KTtcblxuICAgICAgICB9IGVsc2UgaWYgKHBvcykge1xuICAgICAgICAgICAgcGFuKHBvaW50KTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhcmdldCA9IGV2LnRvRWxlbWVudCB8fCBldi50YXJnZXQ7XG4gICAgICAgICAgICB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldCAhPT0gZWwgJiYgdGFyZ2V0LnBhcmVudE5vZGUpIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICBtb3VzZW1vdmUocG9pbnQsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uY2xpY2soZXYpIHtcbiAgICAgICAgaWYgKCFwYW5uZWQpIGNsaWNrKG1vdXNlUG9zKGV2KSwgZXYpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uZG91YmxlY2xpY2soZXYpIHtcbiAgICAgICAgZG91YmxlY2xpY2sobW91c2VQb3MoZXYpLCBldik7XG4gICAgICAgIHpvb20oJ3doZWVsJywgSW5maW5pdHkgKiAoZXYuc2hpZnRLZXkgPyAtMSA6IDEpLCBtb3VzZVBvcyhldikpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbHdoZWVsKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmaXJlZm94ID0gL0ZpcmVmb3gvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgc2FmYXJpID0gL1NhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIS9DaHJvbShpdW18ZSkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgdGltZSA9IHdpbmRvdy5wZXJmb3JtYW5jZSB8fCBEYXRlO1xuXG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgd2hlZWwsIGZhbHNlKTtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V3aGVlbCcsIG1vdXNld2hlZWwsIGZhbHNlKTtcblxuICAgICAgICB2YXIgbGFzdEV2ZW50ID0gMDtcblxuICAgICAgICB2YXIgdHlwZSA9IG51bGw7XG4gICAgICAgIHZhciB0eXBlVGltZW91dCA9IG51bGw7XG4gICAgICAgIHZhciBpbml0aWFsVmFsdWUgPSBudWxsO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNjcm9sbCh2YWx1ZSwgZXYpIHtcbiAgICAgICAgICAgIHZhciBzdGFtcCA9IHRpbWUubm93KCk7XG4gICAgICAgICAgICB2YXIgdGltZURlbHRhID0gc3RhbXAgLSBsYXN0RXZlbnQ7XG4gICAgICAgICAgICBsYXN0RXZlbnQgPSBzdGFtcDtcblxuICAgICAgICAgICAgdmFyIHBvaW50ID0gbW91c2VQb3MoZXYpO1xuXG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IDAgJiYgKHZhbHVlICUgNC4wMDAyNDQxNDA2MjUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIG1vdXNlIHdoZWVsIGV2ZW50LlxuICAgICAgICAgICAgICAgIHR5cGUgPSAnd2hlZWwnO1xuICAgICAgICAgICAgICAgIC8vIE5vcm1hbGl6ZSB0aGlzIHZhbHVlIHRvIG1hdGNoIHRyYWNrcGFkLlxuICAgICAgICAgICAgICAgIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSAvIDQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSAhPT0gMCAmJiBNYXRoLmFicyh2YWx1ZSkgPCA0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIHRyYWNrcGFkIGV2ZW50IGJlY2F1c2UgaXQgaXMgc28gc21hbGwuXG4gICAgICAgICAgICAgICAgdHlwZSA9ICd0cmFja3BhZCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRpbWVEZWx0YSA+IDQwMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgbGlrZWx5IGEgbmV3IHNjcm9sbCBhY3Rpb24uXG4gICAgICAgICAgICAgICAgdHlwZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgLy8gU3RhcnQgYSB0aW1lb3V0IGluIGNhc2UgdGhpcyB3YXMgYSBzaW5ndWxhciBldmVudCwgYW5kIGRlbHkgaXRcbiAgICAgICAgICAgICAgICAvLyBieSB1cCB0byA0MG1zLlxuICAgICAgICAgICAgICAgIHR5cGVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICd3aGVlbCc7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHR5cGUsIC1pbml0aWFsVmFsdWUsIHBvaW50KTtcbiAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVwZWF0aW5nIGV2ZW50LCBidXQgd2UgZG9uJ3Qga25vdyB0aGUgdHlwZSBvZiBldmVudFxuICAgICAgICAgICAgICAgIC8vIGp1c3QgeWV0LiBJZiB0aGUgZGVsdGEgcGVyIHRpbWUgaXMgc21hbGwsIHdlIGFzc3VtZSBpdCdzIGFcbiAgICAgICAgICAgICAgICAvLyBmYXN0IHRyYWNrcGFkOyBvdGhlcndpc2Ugd2Ugc3dpdGNoIGludG8gd2hlZWwgbW9kZS5cbiAgICAgICAgICAgICAgICB0eXBlID0gKE1hdGguYWJzKHRpbWVEZWx0YSAqIHZhbHVlKSA8IDIwMCkgPyAndHJhY2twYWQnIDogJ3doZWVsJztcblxuICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgZGVsYXllZCBldmVudCBpc24ndCBmaXJlZCBhZ2FpbiwgYmVjYXVzZSB3ZVxuICAgICAgICAgICAgICAgIC8vIGFjY3VtdWxhdGUgdGhlIHByZXZpb3VzIGV2ZW50ICh3aGljaCB3YXMgbGVzcyB0aGFuIDQwbXMgYWdvKSBpbnRvXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBldmVudC5cbiAgICAgICAgICAgICAgICBpZiAodHlwZVRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHR5cGVUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZVRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBpbml0aWFsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTbG93IGRvd24gem9vbSBpZiBzaGlmdCBrZXkgaXMgaGVsZCBmb3IgbW9yZSBwcmVjaXNlIHpvb21pbmdcbiAgICAgICAgICAgIGlmIChldi5zaGlmdEtleSAmJiB2YWx1ZSkgdmFsdWUgPSB2YWx1ZSAvIDQ7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZmlyZSB0aGUgY2FsbGJhY2sgaWYgd2UgYWN0dWFsbHkga25vdyB3aGF0IHR5cGUgb2Ygc2Nyb2xsaW5nXG4gICAgICAgICAgICAvLyBkZXZpY2UgdGhlIHVzZXIgdXNlcy5cbiAgICAgICAgICAgIGlmICh0eXBlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sodHlwZSwgLXZhbHVlLCBwb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gZS5kZWx0YVk7XG4gICAgICAgICAgICAvLyBGaXJlZm94IGRvdWJsZXMgdGhlIHZhbHVlcyBvbiByZXRpbmEgc2NyZWVucy4uLlxuICAgICAgICAgICAgaWYgKGZpcmVmb3ggJiYgZS5kZWx0YU1vZGUgPT09IHdpbmRvdy5XaGVlbEV2ZW50LkRPTV9ERUxUQV9QSVhFTCkgZGVsdGFZIC89IGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gd2luZG93LldoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIGRlbHRhWSAqPSA0MDtcbiAgICAgICAgICAgIHNjcm9sbChkZWx0YVksIGUpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2V3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gLWUud2hlZWxEZWx0YVk7XG4gICAgICAgICAgICBpZiAoc2FmYXJpKSBkZWx0YVkgPSBkZWx0YVkgLyAzO1xuICAgICAgICAgICAgc2Nyb2xsKGRlbHRhWSwgZSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbkludGVyYWN0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRlZCk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBDYW52YXMgPSByZXF1aXJlKCcuLi91dGlsL2NhbnZhcycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG5cbnZhciBTdHlsZSA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlJyk7XG52YXIgQW5pbWF0aW9uTG9vcCA9IHJlcXVpcmUoJy4uL3N0eWxlL2FuaW1hdGlvbl9sb29wJyk7XG52YXIgUGFpbnRlciA9IHJlcXVpcmUoJy4uL3JlbmRlci9wYWludGVyJyk7XG5cbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuLi9nZW8vdHJhbnNmb3JtJyk7XG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xudmFyIEhhbmRsZXJzID0gcmVxdWlyZSgnLi9oYW5kbGVycycpO1xudmFyIENhbWVyYSA9IHJlcXVpcmUoJy4vY2FtZXJhJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBMYXRMbmdCb3VuZHMgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQXR0cmlidXRpb24gPSByZXF1aXJlKCcuL2NvbnRyb2wvYXR0cmlidXRpb24nKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbWFwIGluc3RhbmNlLlxuICogQGNsYXNzIE1hcFxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbnRhaW5lciBIVE1MIGVsZW1lbnQgdG8gaW5pdGlhbGl6ZSB0aGUgbWFwIGluIChvciBlbGVtZW50IGlkIGFzIHN0cmluZylcbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW5ab29tPTBdIE1pbmltdW0gem9vbSBvZiB0aGUgbWFwXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4Wm9vbT0yMF0gTWF4aW11bSB6b29tIG9mIHRoZSBtYXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnN0eWxlIE1hcCBzdHlsZSBhbmQgZGF0YSBzb3VyY2UgZGVmaW5pdGlvbiAoZWl0aGVyIGEgSlNPTiBvYmplY3Qgb3IgYSBKU09OIFVSTCksIGRlc2NyaWJlZCBpbiB0aGUgW3N0eWxlIHJlZmVyZW5jZV0oaHR0cHM6Ly9tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuaGFzaD1mYWxzZV0gSWYgYHRydWVgLCB0aGUgbWFwIHdpbGwgdHJhY2sgYW5kIHVwZGF0ZSB0aGUgcGFnZSBVUkwgYWNjb3JkaW5nIHRvIG1hcCBwb3NpdGlvblxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbnRlcmFjdGl2ZT10cnVlXSBJZiBgZmFsc2VgLCBubyBtb3VzZSwgdG91Y2gsIG9yIGtleWJvYXJkIGxpc3RlbmVycyBhcmUgYXR0YWNoZWQgdG8gdGhlIG1hcCwgc28gaXQgd2lsbCBub3QgcmVzcG9uZCB0byBpbnB1dFxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5jbGFzc2VzIFN0eWxlIGNsYXNzIG5hbWVzIHdpdGggd2hpY2ggdG8gaW5pdGlhbGl6ZSB0aGUgbWFwXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9ZmFsc2VdIElmIGB0cnVlYCwgbWFwIGNyZWF0aW9uIHdpbGwgZmFpbCBpZiB0aGUgaW1wbGVtZW50YXRpb24gZGV0ZXJtaW5lcyB0aGF0IHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgY3JlYXRlZCBXZWJHTCBjb250ZXh0IHdvdWxkIGJlIGRyYW1hdGljYWxseSBsb3dlciB0aGFuIGV4cGVjdGVkLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXI9ZmFsc2VdIElmIGB0cnVlYCwgVGhlIG1hcHMgY2FudmFzIGNhbiBiZSBleHBvcnRlZCB0byBhIFBORyB1c2luZyBgbWFwLmdldENhbnZhcygpLnRvRGF0YVVSTCgpO2AuIFRoaXMgaXMgZmFsc2UgYnkgZGVmYXVsdCBhcyBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgbWFwID0gbmV3IG1hcGJveGdsLk1hcCh7XG4gKiAgIGNvbnRhaW5lcjogJ21hcCcsXG4gKiAgIGNlbnRlcjogWzM3Ljc3MjUzNywgLTEyMi40MjA2NzldLFxuICogICB6b29tOiAxMyxcbiAqICAgc3R5bGU6IHN0eWxlX29iamVjdCxcbiAqICAgaGFzaDogdHJ1ZVxuICogfSk7XG4gKi9cbnZhciBNYXAgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB1dGlsLmluaGVyaXQodGhpcy5vcHRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuYW5pbWF0aW9uTG9vcCA9IG5ldyBBbmltYXRpb25Mb29wKCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSBuZXcgVHJhbnNmb3JtKG9wdGlvbnMubWluWm9vbSwgb3B0aW9ucy5tYXhab29tKTtcblxuICAgIGlmIChvcHRpb25zLm1heEJvdW5kcykge1xuICAgICAgICB2YXIgYiA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KG9wdGlvbnMubWF4Qm91bmRzKTtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2UgPSBbYi5nZXRTb3V0aCgpLCBiLmdldE5vcnRoKCldO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZSA9IFtiLmdldFdlc3QoKSwgYi5nZXRFYXN0KCldO1xuICAgIH1cblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFN0eWxlRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRTb3VyY2VFdmVudCcsXG4gICAgICAgICdfZm9yd2FyZExheWVyRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRUaWxlRXZlbnQnLFxuICAgICAgICAnX29uU3R5bGVMb2FkJyxcbiAgICAgICAgJ19vblN0eWxlQ2hhbmdlJyxcbiAgICAgICAgJ19vblNvdXJjZUFkZCcsXG4gICAgICAgICdfb25Tb3VyY2VSZW1vdmUnLFxuICAgICAgICAnX29uU291cmNlVXBkYXRlJyxcbiAgICAgICAgJ3VwZGF0ZScsXG4gICAgICAgICdyZW5kZXInXG4gICAgXSwgdGhpcyk7XG5cbiAgICB0aGlzLl9zZXR1cENvbnRhaW5lcigpO1xuICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuXG4gICAgdGhpcy5vbignbW92ZScsIHRoaXMudXBkYXRlKTtcbiAgICB0aGlzLm9uKCd6b29tJywgdGhpcy51cGRhdGUuYmluZCh0aGlzLCB0cnVlKSk7XG4gICAgdGhpcy5vbignbW92ZWVuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3Auc2V0KDMwMCk7IC8vIHRleHQgZmFkaW5nXG4gICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuaGFuZGxlcnMgPSBvcHRpb25zLmludGVyYWN0aXZlICYmIG5ldyBIYW5kbGVycyh0aGlzKTtcblxuICAgIHRoaXMuX2hhc2ggPSBvcHRpb25zLmhhc2ggJiYgKG5ldyBIYXNoKCkpLmFkZFRvKHRoaXMpO1xuICAgIC8vIGRvbid0IHNldCBwb3NpdGlvbiBmcm9tIG9wdGlvbnMgaWYgc2V0IHRocm91Z2ggaGFzaFxuICAgIGlmICghdGhpcy5faGFzaCB8fCAhdGhpcy5faGFzaC5fb25IYXNoQ2hhbmdlKCkpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8ob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VzID0ge307XG4gICAgdGhpcy5zdGFja3MgPSB7fTtcbiAgICB0aGlzLl9jbGFzc2VzID0ge307XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgaWYgKG9wdGlvbnMuY2xhc3NlcykgdGhpcy5zZXRDbGFzc2VzKG9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgaWYgKG9wdGlvbnMuc3R5bGUpIHRoaXMuc2V0U3R5bGUob3B0aW9ucy5zdHlsZSk7XG4gICAgaWYgKG9wdGlvbnMuYXR0cmlidXRpb25Db250cm9sKSB0aGlzLmFkZENvbnRyb2wobmV3IEF0dHJpYnV0aW9uKCkpO1xufTtcblxudXRpbC5leHRlbmQoTWFwLnByb3RvdHlwZSwgRXZlbnRlZCk7XG51dGlsLmV4dGVuZChNYXAucHJvdG90eXBlLCBDYW1lcmEucHJvdG90eXBlKTtcbnV0aWwuZXh0ZW5kKE1hcC5wcm90b3R5cGUsIC8qKiBAbGVuZHMgTWFwLnByb3RvdHlwZSAqL3tcblxuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICAgIHpvb206IDAsXG4gICAgICAgIGJlYXJpbmc6IDAsXG4gICAgICAgIHBpdGNoOiAwLFxuXG4gICAgICAgIG1pblpvb206IDAsXG4gICAgICAgIG1heFpvb206IDIwLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICBoYXNoOiBmYWxzZSxcblxuICAgICAgICBhdHRyaWJ1dGlvbkNvbnRyb2w6IHRydWUsXG5cbiAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogZmFsc2UsXG4gICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2VcbiAgICB9LFxuXG4gICAgYWRkQ29udHJvbDogZnVuY3Rpb24oY29udHJvbCkge1xuICAgICAgICBjb250cm9sLmFkZFRvKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHR5cGVkZWYge09iamVjdH0gW3N0eWxlT3B0aW9uc11cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtzdHlsZU9wdGlvbnMudHJhbnNpdGlvbj10cnVlXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHN0eWxlIGNsYXNzIHRvIGEgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2xhc3MgbmFtZSBvZiBzdHlsZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7c3R5bGVPcHRpb25zfSBvcHRpb25zXG4gICAgICogQGZpcmVzIGNoYW5nZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZENsYXNzOiBmdW5jdGlvbihrbGFzcywgb3B0aW9ucykge1xuICAgICAgICBpZiAodGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc10gPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIHN0eWxlIGNsYXNzIGZyb20gYSBtYXBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBuYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghdGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBhZGQgbW9yZSB0aGFuIG9uZSBjbGFzc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBrbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0Q2xhc3NlczogZnVuY3Rpb24oa2xhc3Nlcywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLl9jbGFzc2VzID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc2VzW2ldXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcywgb3B0aW9ucyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoZWNrIHdoZXRoZXIgYSBzdHlsZSBjbGFzcyBpcyBhY3RpdmVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBOYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgYWN0aXZlIHN0eWxlIGNsYXNzZXNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldENsYXNzZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fY2xhc3Nlcyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIERldGVjdCB0aGUgbWFwJ3MgbmV3IHdpZHRoIGFuZCBoZWlnaHQgYW5kIHJlc2l6ZSBpdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlc2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDAsIGhlaWdodCA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGggfHwgNDAwO1xuICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAzMDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jYW52YXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMudHJhbnNmb3JtLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0uX2NvbnN0cmFpbigpO1xuXG4gICAgICAgIHRoaXMucGFpbnRlci5yZXNpemUod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIC5maXJlKCdtb3Zlc3RhcnQnKVxuICAgICAgICAgICAgLmZpcmUoJ21vdmUnKVxuICAgICAgICAgICAgLmZpcmUoJ3Jlc2l6ZScpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1hcCdzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN9XG4gICAgICovXG4gICAgZ2V0Qm91bmRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyBQb2ludCgwLCAwKSksXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKHRoaXMudHJhbnNmb3JtLnNpemUpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHBpeGVsIGNvb3JkaW5hdGVzIChyZWxhdGl2ZSB0byBtYXAgY29udGFpbmVyKSBnaXZlbiBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IGB4YCBhbmQgYHlgIGNvb3JkaW5hdGVzXG4gICAgICovXG4gICAgcHJvamVjdDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybS5sb2NhdGlvblBvaW50KExhdExuZy5jb252ZXJ0KGxhdGxuZykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGdpdmVuIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHBvaW50IFt4LCB5XSBwaXhlbCBjb29yZGluYXRlc1xuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgdW5wcm9qZWN0OiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZmVhdHVyZXMgYXQgYSBwb2ludCAoW3gsIHldKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBwb2ludCBbeCwgeV0gcGl4ZWwgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwYXJhbXMucmFkaXVzPTBdIE9wdGlvbmFsLiBSYWRpdXMgaW4gcGl4ZWxzIHRvIHNlYXJjaCBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMubGF5ZXIgT3B0aW9uYWwuIE9ubHkgcmV0dXJuIGZlYXR1cmVzIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMudHlwZSBPcHRpb25hbC4gRWl0aGVyIGByYXN0ZXJgIG9yIGB2ZWN0b3JgXG4gICAgICogQHBhcmFtIHtmZWF0dXJlc0F0Q2FsbGJhY2t9IGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcmVzcG9uc2VcbiAgICAgKlxuICAgICAqIEBjYWxsYmFjayBmZWF0dXJlc0F0Q2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge09iamVjdHxudWxsfSBlcnIgRXJyb3IgX0lmIGFueV9cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmZWF0dXJlcyBEaXNwbGF5cyBhIEpTT04gYXJyYXkgb2YgZmVhdHVyZXMgZ2l2ZW4gdGhlIHBhc3NlZCBwYXJhbWV0ZXJzIG9mIGBmZWF0dXJlc0F0YFxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5mZWF0dXJlc0F0KFsxMCwgMjBdLCB7IHJhZGl1czogMTAgfSwgZnVuY3Rpb24oZXJyLCBmZWF0dXJlcykge1xuICAgICAqICAgY29uc29sZS5sb2coZmVhdHVyZXMpO1xuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBjb29yZCA9IHRoaXMudHJhbnNmb3JtLnBvaW50Q29vcmRpbmF0ZShQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgICAgIHRoaXMuc3R5bGUuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgbWFwJ3Mgc3R5bGUgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3R5bGUgQSBzdHlsZSBvYmplY3QgZm9ybWF0dGVkIGFzIEpTT05cbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRTdHlsZTogZnVuY3Rpb24oc3R5bGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGVcbiAgICAgICAgICAgICAgICAub2ZmKCdsb2FkJywgdGhpcy5fb25TdHlsZUxvYWQpXG4gICAgICAgICAgICAgICAgLm9mZignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vblN0eWxlQ2hhbmdlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ3NvdXJjZS5hZGQnLCB0aGlzLl9vblNvdXJjZUFkZClcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmxvYWQnLCB0aGlzLl9vblNvdXJjZVVwZGF0ZSlcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UuZXJyb3InLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLmFkZCcsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCd0aWxlLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLl9yZW1vdmUoKTtcblxuICAgICAgICAgICAgdGhpcy5vZmYoJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5vZmYoJ3BpdGNoJywgdGhpcy5zdHlsZS5fcmVkb1BsYWNlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN0eWxlKSB7XG4gICAgICAgICAgICB0aGlzLnN0eWxlID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2UgaWYgKHN0eWxlIGluc3RhbmNlb2YgU3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBuZXcgU3R5bGUoc3R5bGUsIHRoaXMuYW5pbWF0aW9uTG9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0eWxlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9vblN0eWxlTG9hZClcbiAgICAgICAgICAgIC5vbignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdGhpcy5fb25TdHlsZUNoYW5nZSlcbiAgICAgICAgICAgIC5vbignc291cmNlLmFkZCcsIHRoaXMuX29uU291cmNlQWRkKVxuICAgICAgICAgICAgLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5sb2FkJywgdGhpcy5fb25Tb3VyY2VVcGRhdGUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgLm9uKCdsYXllci5hZGQnLCB0aGlzLl9mb3J3YXJkTGF5ZXJFdmVudClcbiAgICAgICAgICAgIC5vbignbGF5ZXIucmVtb3ZlJywgdGhpcy5fZm9yd2FyZExheWVyRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCd0aWxlLmxvYWQnLCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpO1xuXG4gICAgICAgIHRoaXMub24oJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICB0aGlzLm9uKCdwaXRjaCcsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBzb3VyY2UgdG8gdGhlIG1hcCBzdHlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJRCBvZiB0aGUgc291cmNlLiBNdXN0IG5vdCBiZSB1c2VkIGJ5IGFueSBleGlzdGluZyBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBzb3VyY2Ugc3BlY2lmaWNhdGlvbiwgZm9sbG93aW5nIHRoZVxuICAgICAqIFtNYXBib3ggR0wgU3R5bGUgUmVmZXJlbmNlXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNzb3VyY2VzKVxuICAgICAqIEBmaXJlcyBzb3VyY2UuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkU291cmNlOiBmdW5jdGlvbihpZCwgc291cmNlKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuYWRkU291cmNlKGlkLCBzb3VyY2UpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFuIGV4aXN0aW5nIHNvdXJjZSBmcm9tIHRoZSBtYXAgc3R5bGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSUQgb2YgdGhlIHNvdXJjZSB0byByZW1vdmVcbiAgICAgKiBAZmlyZXMgc291cmNlLnJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZVNvdXJjZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5yZW1vdmVTb3VyY2UoaWQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBzdHlsZSBzb3VyY2Ugb2JqZWN0IHdpdGggdGhlIGdpdmVuIGBpZGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgc291cmNlIElEXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRTb3VyY2U6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFNvdXJjZShpZCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGxheWVyIHRvIHRoZSBtYXAgc3R5bGUuIFRoZSBsYXllciB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGUgbGF5ZXIgd2l0aFxuICAgICAqIElEIGBiZWZvcmVgLCBvciBhcHBlbmRlZCBpZiBgYmVmb3JlYCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7U3R5bGVMYXllcnxPYmplY3R9IGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSBiZWZvcmUgIElEIG9mIGFuIGV4aXN0aW5nIGxheWVyIHRvIGluc2VydCBiZWZvcmVcbiAgICAgKiBAZmlyZXMgbGF5ZXIuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkTGF5ZXI6IGZ1bmN0aW9uKGxheWVyLCBiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5hZGRMYXllcihsYXllciwgYmVmb3JlKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gYGlkYCBmcm9tIHRoZSBtYXAuIEFueSBsYXllcnMgd2hpY2ggcmVmZXIgdG8gdGhlXG4gICAgICogc3BlY2lmaWVkIGxheWVyIHZpYSBhIGByZWZgIHByb3BlcnR5IGFyZSBhbHNvIHJlbW92ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgbGF5ZXIgaWRcbiAgICAgKiBAZmlyZXMgbGF5ZXIucmVtb3ZlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZUxheWVyOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB0aGlzLnN0eWxlLnJlbW92ZUxheWVyKGlkKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZmlsdGVyIGZvciBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXIgZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0RmlsdGVyOiBmdW5jdGlvbihsYXllciwgZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuc2V0RmlsdGVyKGxheWVyLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBmaWx0ZXIgZm9yIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICovXG4gICAgZ2V0RmlsdGVyOiBmdW5jdGlvbihsYXllcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHlsZS5nZXRGaWx0ZXIobGF5ZXIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHZhbHVlIG9mIGEgcGFpbnQgcHJvcGVydHkgaW4gYSBnaXZlbiBzdHlsZSBsYXllci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYXllciBJRCBvZiBhIGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgbmFtZSBvZiBhIHBhaW50IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIHBhaW50IHByb3Blcnk7IG11c3QgaGF2ZSB0aGUgdHlwZSBhcHByb3ByaWF0ZSBmb3IgdGhlIHByb3BlcnR5IGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB0aGlzLnN0eWxlLnNldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcyk7XG4gICAgICAgIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMudXBkYXRlKHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB2YWx1ZSBvZiBhIHBhaW50IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBwYWludCBwcm9wZXJ0eVxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0ga2xhc3Mgb3B0aW9uYWwgY2xhc3Mgc3BlY2lmaWVyIGZvciB0aGUgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdmFsdWUgZm9yIHRoZSBwYWludCBwcm9wZXJ5XG4gICAgICovXG4gICAgZ2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIGtsYXNzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIGtsYXNzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB2YWx1ZSBvZiBhIGxheW91dCBwcm9wZXJ0eSBpbiBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIGEgbGF5b3V0IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIGxheW91dCBwcm9wZXJ5OyBtdXN0IGhhdmUgdGhlIHR5cGUgYXBwcm9wcmlhdGUgZm9yIHRoZSBwcm9wZXJ0eSBhcyBkZWZpbmVkIGluIHRoZSBbU3R5bGUgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXBib3gtZ2wtc3R5bGUtc3BlYy8pXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnN0eWxlLnNldExheW91dFByb3BlcnR5KGxheWVyLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHZhbHVlIG9mIGEgbGF5b3V0IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMgeyp9IHZhbHVlIGZvciB0aGUgbGF5b3V0IHByb3BlcnlcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGF5b3V0UHJvcGVydHkobGF5ZXIsIG5hbWUpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIE1hcCdzIGNvbnRhaW5lciBhcyBhbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGFpbmVyIGZvciB0aGUgbWFwIGBjYW52YXNgIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBhZGQgbm9uLUdMIG92ZXJsYXlzIHRvIHRoZSBtYXAsIHlvdSBzaG91bGQgYXBwZW5kIHRoZW0gdG8gdGhpcyBlbGVtZW50LiBUaGlzXG4gICAgICogaXMgdGhlIGVsZW1lbnQgdG8gd2hpY2ggZXZlbnQgYmluZGluZ3MgZm9yIG1hcCBpbnRlcmFjdGl2aXR5IHN1Y2ggYXMgcGFubmluZyBhbmQgem9vbWluZyBhcmVcbiAgICAgKiBhdHRhY2hlZC4gSXQgd2lsbCByZWNlaXZlIGJ1YmJsZWQgZXZlbnRzIGZvciBjaGlsZCBlbGVtZW50cyBzdWNoIGFzIHRoZSBgY2FudmFzYCwgYnV0IG5vdCBmb3JcbiAgICAgKiBtYXAgY29udHJvbHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENhbnZhc0NvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYW52YXNDb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgTWFwJ3MgY2FudmFzIGFzIGFuIEhUTUwgY2FudmFzXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fSBjYW52YXNcbiAgICAgKi9cbiAgICBnZXRDYW52YXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FudmFzLmdldEVsZW1lbnQoKTtcbiAgICB9LFxuXG4gICAgX3NldHVwQ29udGFpbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGlkID0gdGhpcy5vcHRpb25zLmNvbnRhaW5lcjtcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xuICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtbWFwJyk7XG5cbiAgICAgICAgdmFyIGNhbnZhc0NvbnRhaW5lciA9IHRoaXMuX2NhbnZhc0NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jYW52YXMtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgY2FudmFzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWludGVyYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2FudmFzID0gbmV3IENhbnZhcyh0aGlzLCBjYW52YXNDb250YWluZXIpO1xuXG4gICAgICAgIHZhciBjb250cm9sQ29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWNvbnRyb2wtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgdmFyIGNvcm5lcnMgPSB0aGlzLl9jb250cm9sQ29ybmVycyA9IHt9O1xuICAgICAgICBbJ3RvcC1sZWZ0JywgJ3RvcC1yaWdodCcsICdib3R0b20tbGVmdCcsICdib3R0b20tcmlnaHQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIGNvcm5lcnNbcG9zXSA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jdHJsLScgKyBwb3MsIGNvbnRyb2xDb250YWluZXIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgX3NldHVwUGFpbnRlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnbCA9IHRoaXMuX2NhbnZhcy5nZXRXZWJHTENvbnRleHQoe1xuICAgICAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogdGhpcy5vcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQsXG4gICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRoaXMub3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXJcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFnbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0wnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFpbnRlciA9IG5ldyBQYWludGVyKGdsLCB0aGlzLnRyYW5zZm9ybSk7XG4gICAgfSxcblxuICAgIF9jb250ZXh0TG9zdDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIGJyb3dzZXIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRleHRSZXN0b3JlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJcyB0aGlzIG1hcCBmdWxseSBsb2FkZWQ/IElmIHRoZSBzdHlsZSBpc24ndCBsb2FkZWRcbiAgICAgKiBvciBpdCBoYXMgYSBjaGFuZ2UgdG8gdGhlIHNvdXJjZXMgb3Igc3R5bGUgdGhhdCBpc24ndFxuICAgICAqIHByb3BhZ2F0ZWQgdG8gaXRzIHN0eWxlLCByZXR1cm4gZmFsc2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gd2hldGhlciB0aGUgbWFwIGlzIGxvYWRlZFxuICAgICAqL1xuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHlsZURpcnR5IHx8IHRoaXMuX3NvdXJjZXNEaXJ0eSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUgJiYgIXRoaXMuc3R5bGUubG9hZGVkKCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhpcyBtYXAncyBzdHlsZSBhbmQgcmUtcmVuZGVyIHRoZSBtYXAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdXBkYXRlU3R5bGUgbmV3IHN0eWxlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXBkYXRlU3R5bGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0eWxlKSByZXR1cm4gdGhpcztcblxuICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gdGhpcy5fc3R5bGVEaXJ0eSB8fCB1cGRhdGVTdHlsZTtcbiAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHdoZW4gYSAocmUtKXJlbmRlciBvZiB0aGUgbWFwIGlzIHJlcXVpcmVkLCBlLmcuIHdoZW4gdGhlXG4gICAgICogdXNlciBwYW5uZWQgb3Igem9vbWVkLGYgb3IgbmV3IGRhdGEgaXMgYXZhaWxhYmxlLlxuICAgICAqIEByZXR1cm5zIHtNYXB9IHRoaXNcbiAgICAgKi9cbiAgICByZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiB0aGlzLl9zdHlsZURpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnN0eWxlLl9yZWNhbGN1bGF0ZSh0aGlzLnRyYW5zZm9ybS56b29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnN0eWxlICYmIHRoaXMuX3NvdXJjZXNEaXJ0eSAmJiAhdGhpcy5fc291cmNlc0RpcnR5VGltZW91dCkge1xuICAgICAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSwgNTApO1xuICAgICAgICAgICAgdGhpcy5zdHlsZS5fdXBkYXRlU291cmNlcyh0aGlzLnRyYW5zZm9ybSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhaW50ZXIucmVuZGVyKHRoaXMuc3R5bGUsIHtcbiAgICAgICAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxuICAgICAgICAgICAgdmVydGljZXM6IHRoaXMudmVydGljZXMsXG4gICAgICAgICAgICByb3RhdGluZzogdGhpcy5yb3RhdGluZyxcbiAgICAgICAgICAgIHpvb21pbmc6IHRoaXMuem9vbWluZ1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmZpcmUoJ3JlbmRlcicpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRlZCgpICYmICF0aGlzLl9sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2ZyYW1lSWQgPSBudWxsO1xuXG4gICAgICAgIGlmICghdGhpcy5hbmltYXRpb25Mb29wLnN0b3BwZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fc291cmNlc0RpcnR5IHx8IHRoaXMuX3JlcGFpbnQgfHwgIXRoaXMuYW5pbWF0aW9uTG9vcC5zdG9wcGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRGVzdHJveXMgdGhlIG1hcCdzIHVuZGVybHlpbmcgcmVzb3VyY2VzLCBpbmNsdWRpbmcgd2ViIHdvcmtlcnMuXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYXNoKSB0aGlzLl9oYXNoLnJlbW92ZSgpO1xuICAgICAgICBicm93c2VyLmNhbmNlbEZyYW1lKHRoaXMuX2ZyYW1lSWQpO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fc291cmNlc0RpcnR5VGltZW91dCk7XG4gICAgICAgIHRoaXMuc2V0U3R5bGUobnVsbCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcmVyZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiAhdGhpcy5fZnJhbWVJZCkge1xuICAgICAgICAgICAgdGhpcy5fZnJhbWVJZCA9IGJyb3dzZXIuZnJhbWUodGhpcy5yZW5kZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU3R5bGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3N0eWxlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU291cmNlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy5maXJlKGUudHlwZSwgdXRpbC5leHRlbmQoe3N0eWxlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgX2ZvcndhcmRMYXllckV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkVGlsZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9vblN0eWxlTG9hZDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLnN0eWxlLl9jYXNjYWRlKHRoaXMuX2NsYXNzZXMsIHt0cmFuc2l0aW9uOiBmYWxzZX0pO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU3R5bGVDaGFuZ2U6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGUodHJ1ZSk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTdHlsZUV2ZW50KGUpO1xuICAgIH0sXG5cbiAgICBfb25Tb3VyY2VBZGQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGUuc291cmNlO1xuICAgICAgICBpZiAoc291cmNlLm9uQWRkKVxuICAgICAgICAgICAgc291cmNlLm9uQWRkKHRoaXMpO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQoZSk7XG4gICAgfSxcblxuICAgIF9vblNvdXJjZVJlbW92ZTogZnVuY3Rpb24oZSkge1xuICAgICAgICB2YXIgc291cmNlID0gZS5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2Uub25SZW1vdmUpXG4gICAgICAgICAgICBzb3VyY2Uub25SZW1vdmUodGhpcyk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU291cmNlVXBkYXRlOiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9XG59KTtcblxudXRpbC5leHRlbmRBbGwoTWFwLnByb3RvdHlwZSwge1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlIGRlYnVnZ2luZyBtb2RlXG4gICAgICpcbiAgICAgKiBAbmFtZSBkZWJ1Z1xuICAgICAqIEBtZW1iZXJvZiBNYXBcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfZGVidWc6IGZhbHNlLFxuICAgIGdldCBkZWJ1ZygpIHsgcmV0dXJuIHRoaXMuX2RlYnVnOyB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkgeyB0aGlzLl9kZWJ1ZyA9IHZhbHVlOyB0aGlzLnVwZGF0ZSgpOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2hvdyBjb2xsaXNpb24gYm94ZXM6IHVzZWZ1bCBmb3IgZGVidWdnaW5nIGxhYmVsIHBsYWNlbWVudFxuICAgICAqIGluIHN0eWxlcy5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbGxpc2lvbkRlYnVnXG4gICAgICogQG1lbWJlcm9mIE1hcFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIF9jb2xsaXNpb25EZWJ1ZzogZmFsc2UsXG4gICAgZ2V0IGNvbGxpc2lvbkRlYnVnKCkgeyByZXR1cm4gdGhpcy5fY29sbGlzaW9uRGVidWc7IH0sXG4gICAgc2V0IGNvbGxpc2lvbkRlYnVnKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbGxpc2lvbkRlYnVnID0gdmFsdWU7XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHlsZS5zb3VyY2VzW2ldLnJlbG9hZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3R5bGUuc291cmNlc1tpXS5yZWxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBFbmFibGUgY29udGludW91cyByZXBhaW50IHRvIGFuYWx5emUgcGVyZm9ybWFuY2VcbiAgICAgKlxuICAgICAqIEBuYW1lIHJlcGFpbnRcbiAgICAgKiBAbWVtYmVyb2YgTWFwXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3JlcGFpbnQ6IGZhbHNlLFxuICAgIGdldCByZXBhaW50KCkgeyByZXR1cm4gdGhpcy5fcmVwYWludDsgfSxcbiAgICBzZXQgcmVwYWludCh2YWx1ZSkgeyB0aGlzLl9yZXBhaW50ID0gdmFsdWU7IHRoaXMudXBkYXRlKCk7IH0sXG5cbiAgICAvLyBzaG93IHZlcnRpY2VzXG4gICAgX3ZlcnRpY2VzOiBmYWxzZSxcbiAgICBnZXQgdmVydGljZXMoKSB7IHJldHVybiB0aGlzLl92ZXJ0aWNlczsgfSxcbiAgICBzZXQgdmVydGljZXModmFsdWUpIHsgdGhpcy5fdmVydGljZXMgPSB2YWx1ZTsgdGhpcy51cGRhdGUoKTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9wdXA7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgcG9wdXAgY29tcG9uZW50XG4gKiBAY2xhc3MgUG9wdXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuY2xvc2VCdXR0b25cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gb3B0aW9ucy5jbG9zZU9uQ2xpY2tcbiAqIEBleGFtcGxlXG4gKiB2YXIgdG9vbHRpcCA9IG5ldyBtYXBib3hnbC5Qb3B1cCgpXG4gKiAgIC5zZXRMYXRMbmcobWFwLnVucHJvamVjdChlLnBvaW50KSlcbiAqICAgLnNldEhUTUwoXCI8aDE+SGVsbG8gV29ybGQhPC9oMT5cIilcbiAqICAgLmFkZFRvKG1hcCk7XG4gKi9cbmZ1bmN0aW9uIFBvcHVwKG9wdGlvbnMpIHtcbiAgICB1dGlsLnNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ191cGRhdGVQb3NpdGlvbicsXG4gICAgICAgICdfb25DbGlja0Nsb3NlJ10sXG4gICAgICAgIHRoaXMpO1xufVxuXG5Qb3B1cC5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwgLyoqIEBsZW5kcyBQb3B1cC5wcm90b3R5cGUgKi97XG4gICAgb3B0aW9uczoge1xuICAgICAgICBjbG9zZUJ1dHRvbjogdHJ1ZSxcbiAgICAgICAgY2xvc2VPbkNsaWNrOiB0cnVlXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIHRoZSBwb3B1cCB0byBhIG1hcFxuICAgICAqIEBwYXJhbSB7TWFwfSBtYXBcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmUnLCB0aGlzLl91cGRhdGVQb3NpdGlvbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5fb25DbGlja0Nsb3NlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHBvcHVwIGZyb20gdGhlIG1hcFxuICAgICAqIEBleGFtcGxlXG4gICAgICogdmFyIHBvcHVwID0gbmV3IG1hcGJveGdsLlBvcHVwKCkuYWRkVG8obWFwKTtcbiAgICAgKiBwb3B1cC5yZW1vdmUoKTtcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbWFwKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlJywgdGhpcy5fdXBkYXRlUG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy5fbWFwLm9mZignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX21hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgY29vcmRpbmF0ZXMgb2YgcG9wdXAgZWxlbWVudCByZWxhdGl2ZSB0byBtYXBcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfVxuICAgICAqL1xuICAgIGdldExhdExuZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYXRMbmc7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY29vcmRpbmF0ZXMgb2YgYSBwb3B1cCBlbGVtZW50IHRvIGEgbWFwXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtQb3B1cH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF0TG5nOiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdGhpcy5fbGF0TG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIHRleHQgb25seSBjb250ZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHNldFRleHQ6IGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgdGhpcy5fY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIEhUTUwgY29udGVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRIVE1MOiBmdW5jdGlvbihodG1sKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgICAgICAgdmFyIHRlbXAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib2R5JyksIGNoaWxkO1xuICAgICAgICB0ZW1wLmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjaGlsZCA9IHRlbXAuZmlyc3RDaGlsZDtcbiAgICAgICAgICAgIGlmICghY2hpbGQpIGJyZWFrO1xuICAgICAgICAgICAgdGhpcy5fY29udGVudC5hcHBlbmRDaGlsZChjaGlsZCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1wb3B1cCcsIHRoaXMuX21hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgICAgIHRoaXMuX3RpcCAgICAgPSBET00uY3JlYXRlKCdkaXYnLCAnbWFwYm94Z2wtcG9wdXAtdGlwJywgICAgIHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgICAgICB0aGlzLl93cmFwcGVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLXBvcHVwLWNvbnRlbnQnLCB0aGlzLl9jb250YWluZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNsb3NlQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24gPSBET00uY3JlYXRlKCdidXR0b24nLCAnbWFwYm94Z2wtcG9wdXAtY2xvc2UtYnV0dG9uJywgdGhpcy5fd3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uaW5uZXJIVE1MID0gJyYjMjE1Oyc7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGVudCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlQ29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fY29udGVudCB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fd3JhcHBlcjtcblxuICAgICAgICB3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICAgICAgICAgIG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGhpcy5fY2xvc2VCdXR0b24pO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2xhdExuZyB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBwb3MgPSB0aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sYXRMbmcpLnJvdW5kKCksXG4gICAgICAgICAgICBhbmNob3IgPSB0aGlzLm9wdGlvbnMuYW5jaG9yO1xuXG4gICAgICAgIGlmICghYW5jaG9yKSB7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgaWYgKHBvcy55IDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gWyd0b3AnXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9zLnkgPiB0aGlzLl9tYXAudHJhbnNmb3JtLmhlaWdodCAtIGhlaWdodCkge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFsnYm90dG9tJ107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocG9zLnggPCB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgnbGVmdCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwb3MueCA+IHRoaXMuX21hcC50cmFuc2Zvcm0ud2lkdGggLSB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgncmlnaHQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFuY2hvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBhbmNob3IgPSAnYm90dG9tJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gYW5jaG9yLmpvaW4oJy0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFuY2hvciA9IGFuY2hvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhbmNob3JUcmFuc2xhdGUgPSB7XG4gICAgICAgICAgICAndG9wJzogJ3RyYW5zbGF0ZSgtNTAlLDApJyxcbiAgICAgICAgICAgICd0b3AtbGVmdCc6ICd0cmFuc2xhdGUoMCwwKScsXG4gICAgICAgICAgICAndG9wLXJpZ2h0JzogJ3RyYW5zbGF0ZSgtMTAwJSwwKScsXG4gICAgICAgICAgICAnYm90dG9tJzogJ3RyYW5zbGF0ZSgtNTAlLC0xMDAlKScsXG4gICAgICAgICAgICAnYm90dG9tLWxlZnQnOiAndHJhbnNsYXRlKDAsLTEwMCUpJyxcbiAgICAgICAgICAgICdib3R0b20tcmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC0xMDAlKScsXG4gICAgICAgICAgICAnbGVmdCc6ICd0cmFuc2xhdGUoMCwtNTAlKScsXG4gICAgICAgICAgICAncmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC01MCUpJ1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0O1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gYW5jaG9yVHJhbnNsYXRlKSB7XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1wb3B1cC1hbmNob3ItJyArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtcG9wdXAtYW5jaG9yLScgKyBhbmNob3IpO1xuXG4gICAgICAgIERPTS5zZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCBhbmNob3JUcmFuc2xhdGVbYW5jaG9yXSArICcgdHJhbnNsYXRlKCcgKyBwb3MueCArICdweCwnICsgcG9zLnkgKyAncHgpJyk7XG4gICAgfSxcblxuICAgIF9vbkNsaWNrQ2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFjdG9yO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHRoZSBbQWN0b3IgZGVzaWduIHBhdHRlcm5dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWN0b3JfbW9kZWwpXG4gKiB0aGF0IG1haW50YWlucyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYXN5bmNocm9ub3VzIHRhc2tzIGFuZCB0aGUgb2JqZWN0c1xuICogdGhhdCBzcGluIHRoZW0gb2ZmIC0gaW4gdGhpcyBjYXNlLCB0YXNrcyBsaWtlIHBhcnNpbmcgcGFydHMgb2Ygc3R5bGVzLFxuICogb3duZWQgYnkgdGhlIHN0eWxlc1xuICpcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSB0YXJnZXRcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSBwYXJlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEFjdG9yKHRhcmdldCwgcGFyZW50KSB7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5jYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLmNhbGxiYWNrSUQgPSAwO1xuICAgIHRoaXMucmVjZWl2ZSA9IHRoaXMucmVjZWl2ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0aGlzLnJlY2VpdmUsIGZhbHNlKTtcbn1cblxuQWN0b3IucHJvdG90eXBlLnJlY2VpdmUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG4gICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGEsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJzxyZXNwb25zZT4nKSB7XG4gICAgICAgIGNhbGxiYWNrID0gdGhpcy5jYWxsYmFja3NbZGF0YS5pZF07XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tkYXRhLmlkXTtcbiAgICAgICAgY2FsbGJhY2soZGF0YS5lcnJvciB8fCBudWxsLCBkYXRhLmRhdGEpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEuaWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBpZCA9IGRhdGEuaWQ7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhLCBmdW5jdGlvbihlcnIsIGRhdGEsIGJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIHRoaXMucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICc8cmVzcG9uc2U+JyxcbiAgICAgICAgICAgICAgICBpZDogU3RyaW5nKGlkKSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID8gU3RyaW5nKGVycikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGFcbiAgICAgICAgICAgIH0sIGJ1ZmZlcnMpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhKTtcbiAgICB9XG59O1xuXG5BY3Rvci5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCBidWZmZXJzKSB7XG4gICAgdmFyIGlkID0gbnVsbDtcbiAgICBpZiAoY2FsbGJhY2spIHRoaXMuY2FsbGJhY2tzW2lkID0gdGhpcy5jYWxsYmFja0lEKytdID0gY2FsbGJhY2s7XG4gICAgdGhpcy5wb3N0TWVzc2FnZSh7IHR5cGU6IHR5cGUsIGlkOiBTdHJpbmcoaWQpLCBkYXRhOiBkYXRhIH0sIGJ1ZmZlcnMpO1xufTtcblxuLyoqXG4gKiBXcmFwcGVkIHBvc3RNZXNzYWdlIEFQSSB0aGF0IGFic3RyYWN0cyBhcm91bmQgSUUncyBsYWNrIG9mXG4gKiBgdHJhbnNmZXJMaXN0YCBzdXBwb3J0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmZXJMaXN0XG4gKi9cbkFjdG9yLnByb3RvdHlwZS5wb3N0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCkge1xuICAgIHRyeSB7XG4gICAgICAgIHRoaXMudGFyZ2V0LnBvc3RNZXNzYWdlKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLnRhcmdldC5wb3N0TWVzc2FnZShtZXNzYWdlKTsgLy8gTm8gc3VwcG9ydCBmb3IgdHJhbnNmZXJMaXN0IG9uIElFXG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5nZXRKU09OID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTtcbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgY2FsbGJhY2soZSk7XG4gICAgfTtcbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh4aHIuc3RhdHVzID49IDIwMCAmJiB4aHIuc3RhdHVzIDwgMzAwICYmIHhoci5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0QXJyYXlCdWZmZXIgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpO1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oZSkge1xuICAgICAgICBjYWxsYmFjayhlKTtcbiAgICB9O1xuICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCAzMDAgJiYgeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCB4aHIucmVzcG9uc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0SW1hZ2UgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgIGltZy5jcm9zc09yaWdpbiA9ICdBbm9ueW1vdXMnO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgaW1nKTtcbiAgICB9O1xuICAgIGltZy5zcmMgPSB1cmw7XG4gICAgaW1nLmdldERhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBpbWcud2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWcuaGVpZ2h0O1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIDAsIDApO1xuICAgICAgICByZXR1cm4gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW1nLndpZHRoLCBpbWcuaGVpZ2h0KS5kYXRhO1xuICAgIH07XG4gICAgcmV0dXJuIGltZztcbn07XG5cbmV4cG9ydHMuZ2V0VmlkZW8gPSBmdW5jdGlvbih1cmxzLCBjYWxsYmFjaykge1xuICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgdmlkZW8uY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICB2aWRlby5vbmxvYWRzdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCB2aWRlbyk7XG4gICAgfTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzb3VyY2UnKTtcbiAgICAgICAgcy5zcmMgPSB1cmxzW2ldO1xuICAgICAgICB2aWRlby5hcHBlbmRDaGlsZChzKTtcbiAgICB9XG4gICAgdmlkZW8uZ2V0RGF0YSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdmlkZW87IH07XG4gICAgcmV0dXJuIHZpZGVvO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENhbnZhcyA9IHJlcXVpcmUoJy4vY2FudmFzJyk7XG5cbnZhciBmcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5mcmFtZSA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgcmV0dXJuIGZyYW1lKGZuKTtcbn07XG5cbnZhciBjYW5jZWwgPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNDYW5jZWxBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5jYW5jZWxGcmFtZSA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgY2FuY2VsKGlkKTtcbn07XG5cbmV4cG9ydHMudGltZWQgPSBmdW5jdGlvbiAoZm4sIGR1ciwgY3R4KSB7XG4gICAgaWYgKCFkdXIpIHtcbiAgICAgICAgZm4uY2FsbChjdHgsIDEpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYWJvcnQgPSBmYWxzZSxcbiAgICAgICAgc3RhcnQgPSB3aW5kb3cucGVyZm9ybWFuY2UgPyB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdygpO1xuXG4gICAgZnVuY3Rpb24gdGljayhub3cpIHtcbiAgICAgICAgaWYgKGFib3J0KSByZXR1cm47XG4gICAgICAgIGlmICghd2luZG93LnBlcmZvcm1hbmNlKSBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIGlmIChub3cgPj0gc3RhcnQgKyBkdXIpIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAobm93IC0gc3RhcnQpIC8gZHVyKTtcbiAgICAgICAgICAgIGV4cG9ydHMuZnJhbWUodGljayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBleHBvcnRzLmZyYW1lKHRpY2spO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyBhYm9ydCA9IHRydWU7IH07XG59O1xuXG4vKipcbiAqIFRlc3Qgd2hldGhlciB0aGUgYmFzaWMgSmF2YVNjcmlwdCBhbmQgRE9NIGZlYXR1cmVzIHJlcXVpcmVkIGZvciBNYXBib3ggR0wgYXJlIHByZXNlbnQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0PWZhbHNlXSBJZiBgdHJ1ZWAsIG1hcCBjcmVhdGlvbiB3aWxsIGZhaWwgaWYgdGhlIGltcGxlbWVudGF0aW9uIGRldGVybWluZXMgdGhhdCB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGNyZWF0ZWQgV2ViR0wgY29udGV4dCB3b3VsZCBiZSBkcmFtYXRpY2FsbHkgbG93ZXIgdGhhbiBleHBlY3RlZC5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBNYXBib3ggR0wgc2hvdWxkIGJlIGV4cGVjdGVkIHRvIHdvcmssIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cbmV4cG9ydHMuc3VwcG9ydGVkID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gICAgdmFyIHN1cHBvcnRzID0gW1xuXG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7IH0sXG5cbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnOyB9LFxuXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShBcnJheS5wcm90b3R5cGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZXZlcnkgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZmlsdGVyICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2ggJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5tYXAgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc29tZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2UgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucmVkdWNlUmlnaHQgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShGdW5jdGlvbi5wcm90b3R5cGUgJiYgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpICYmXG4gICAgICAgICAgICAgICAgISEoT2JqZWN0LmtleXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmNyZWF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmlzU2VhbGVkICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5pc0Zyb3plbiAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuaXNFeHRlbnNpYmxlICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5zZWFsICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAnSlNPTicgaW4gd2luZG93ICYmICdwYXJzZScgaW4gSlNPTiAmJiAnc3RyaW5naWZ5JyBpbiBKU09OO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDYW52YXMoKS5zdXBwb3J0c1dlYkdMQ29udGV4dCgob3B0aW9ucyAmJiBvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpIHx8IGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuICdXb3JrZXInIGluIHdpbmRvdzsgfVxuICAgIF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1cHBvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghc3VwcG9ydHNbaV0oKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydHMuaGFyZHdhcmVDb25jdXJyZW5jeSA9IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5IHx8IDg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGV2aWNlUGl4ZWxSYXRpbycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYW52YXM7XG5cbmZ1bmN0aW9uIENhbnZhcyhwYXJlbnQsIGNvbnRhaW5lcikge1xuICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG5cbiAgICBpZiAocGFyZW50ICYmIGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgIHRoaXMuY2FudmFzLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWNhbnZhcycpO1xuICAgICAgICB0aGlzLmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgcGFyZW50Ll9jb250ZXh0TG9zdC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0cmVzdG9yZWQnLCBwYXJlbnQuX2NvbnRleHRSZXN0b3JlZC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIDApO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgIH1cbn1cblxuQ2FudmFzLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgLy8gUmVxdWVzdCB0aGUgcmVxdWlyZWQgY2FudmFzIHNpemUgdGFraW5nIHRoZSBwaXhlbHJhdGlvIGludG8gYWNjb3VudC5cbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHBpeGVsUmF0aW8gKiB3aWR0aDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBwaXhlbFJhdGlvICogaGVpZ2h0O1xuXG4gICAgLy8gTWFpbnRhaW4gdGhlIHNhbWUgY2FudmFzIHNpemUsIHBvdGVudGlhbGx5IGRvd25zY2FsaW5nIGl0IGZvciBIaURQSSBkaXNwbGF5c1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG59O1xuXG52YXIgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyA9IHtcbiAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgIGFscGhhOiB0cnVlLFxuICAgIHN0ZW5jaWw6IHRydWUsXG4gICAgZGVwdGg6IGZhbHNlXG59O1xuXG5DYW52YXMucHJvdG90eXBlLmdldFdlYkdMQ29udGV4dCA9IGZ1bmN0aW9uKGF0dHJpYnV0ZXMpIHtcbiAgICBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe30sIGF0dHJpYnV0ZXMsIHJlcXVpcmVkQ29udGV4dEF0dHJpYnV0ZXMpO1xuXG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldENvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG59O1xuXG5DYW52YXMucHJvdG90eXBlLnN1cHBvcnRzV2ViR0xDb250ZXh0ID0gZnVuY3Rpb24oZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe1xuICAgICAgICBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0OiBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0XG4gICAgfSwgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyk7XG5cbiAgICBpZiAoJ3Byb2JhYmx5U3VwcG9ydHNDb250ZXh0JyBpbiB0aGlzLmNhbnZhcykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXMucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0KCdleHBlcmltZW50YWwtd2ViZ2wnLCBhdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2UgaWYgKCdzdXBwb3J0c0NvbnRleHQnIGluIHRoaXMuY2FudmFzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhcy5zdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN1cHBvcnRzQ29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhd2luZG93LldlYkdMUmVuZGVyaW5nQ29udGV4dCAmJiAhIXRoaXMuZ2V0V2ViR0xDb250ZXh0KGZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpO1xufTtcblxuQ2FudmFzLnByb3RvdHlwZS5nZXRFbGVtZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFjdG9yID0gcmVxdWlyZSgnLi4vYWN0b3InKTtcbnZhciBXZWJXb3JraWZ5ID0gcmVxdWlyZSgnd2Vid29ya2lmeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERpc3BhdGNoZXI7XG5cbmZ1bmN0aW9uIERpc3BhdGNoZXIobGVuZ3RoLCBwYXJlbnQpIHtcbiAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIHRoaXMuY3VycmVudEFjdG9yID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB3b3JrZXIgPSBuZXcgV2ViV29ya2lmeShyZXF1aXJlKCcuLi8uLi9zb3VyY2Uvd29ya2VyJykpO1xuICAgICAgICB2YXIgYWN0b3IgPSBuZXcgQWN0b3Iod29ya2VyLCBwYXJlbnQpO1xuICAgICAgICBhY3Rvci5uYW1lID0gXCJXb3JrZXIgXCIgKyBpO1xuICAgICAgICB0aGlzLmFjdG9ycy5wdXNoKGFjdG9yKTtcbiAgICB9XG59XG5cbkRpc3BhdGNoZXIucHJvdG90eXBlID0ge1xuICAgIGJyb2FkY2FzdDogZnVuY3Rpb24odHlwZSwgZGF0YSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmFjdG9yc1tpXS5zZW5kKHR5cGUsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNlbmQ6IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCB0YXJnZXRJRCwgYnVmZmVycykge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldElEICE9PSAnbnVtYmVyJyB8fCBpc05hTih0YXJnZXRJRCkpIHtcbiAgICAgICAgICAgIC8vIFVzZSByb3VuZCByb2JpbiB0byBzZW5kIHJlcXVlc3RzIHRvIHdlYiB3b3JrZXJzLlxuICAgICAgICAgICAgdGFyZ2V0SUQgPSB0aGlzLmN1cnJlbnRBY3RvciA9ICh0aGlzLmN1cnJlbnRBY3RvciArIDEpICUgdGhpcy5hY3RvcnMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hY3RvcnNbdGFyZ2V0SURdLnNlbmQodHlwZSwgZGF0YSwgY2FsbGJhY2ssIGJ1ZmZlcnMpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0SUQ7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuYWN0b3JzW2ldLnRhcmdldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24gKHRhZ05hbWUsIGNsYXNzTmFtZSwgY29udGFpbmVyKSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlbC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgaWYgKGNvbnRhaW5lcikgY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcbiAgICByZXR1cm4gZWw7XG59O1xuXG52YXIgZG9jU3R5bGUgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU7XG5cbmZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocHJvcHNbaV0gaW4gZG9jU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBwcm9wc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxudmFyIHNlbGVjdFByb3AgPSB0ZXN0UHJvcChbJ3VzZXJTZWxlY3QnLCAnTW96VXNlclNlbGVjdCcsICdXZWJraXRVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKSxcbiAgICB1c2VyU2VsZWN0O1xuZXhwb3J0cy5kaXNhYmxlRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc2VsZWN0UHJvcCkge1xuICAgICAgICB1c2VyU2VsZWN0ID0gZG9jU3R5bGVbc2VsZWN0UHJvcF07XG4gICAgICAgIGRvY1N0eWxlW3NlbGVjdFByb3BdID0gJ25vbmUnO1xuICAgIH1cbn07XG5leHBvcnRzLmVuYWJsZURyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGVjdFByb3ApIHtcbiAgICAgICAgZG9jU3R5bGVbc2VsZWN0UHJvcF0gPSB1c2VyU2VsZWN0O1xuICAgIH1cbn07XG5cbnZhciB0cmFuc2Zvcm1Qcm9wID0gdGVzdFByb3AoWyd0cmFuc2Zvcm0nLCAnV2Via2l0VHJhbnNmb3JtJ10pO1xuZXhwb3J0cy5zZXRUcmFuc2Zvcm0gPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBlbC5zdHlsZVt0cmFuc2Zvcm1Qcm9wXSA9IHZhbHVlO1xufTtcblxuLy8gU3VwcHJlc3MgdGhlIG5leHQgY2xpY2ssIGJ1dCBvbmx5IGlmIGl0J3MgaW1tZWRpYXRlLlxuZnVuY3Rpb24gc3VwcHJlc3NDbGljayhlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG59XG5leHBvcnRzLnN1cHByZXNzQ2xpY2sgPSBmdW5jdGlvbigpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzdXBwcmVzc0NsaWNrLCB0cnVlKTtcbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG4gICAgfSwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIVFRQX1VSTDogJ2h0dHA6Ly9hLnRpbGVzLm1hcGJveC5jb20nLFxuICAgIEhUVFBTX1VSTDogJ2h0dHBzOi8vYS50aWxlcy5tYXBib3guY29tJyxcbiAgICBGT1JDRV9IVFRQUzogdHJ1ZSxcbiAgICBSRVFVSVJFX0FDQ0VTU19UT0tFTjogdHJ1ZVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLyoqXG4gKiBNZXRob2RzIG1peGVkIGluIHRvIG90aGVyIGNsYXNzZXMgZm9yIGV2ZW50IGNhcGFiaWxpdGllcy5cbiAqIEBtaXhpbiBFdmVudGVkXG4gKi9cbnZhciBFdmVudGVkID0ge1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGEgc3BlY2lmaWVkIGV2ZW50IHdpdGggYSBsaXN0ZW5lciBmdW5jdGlvbiB0aGUgbGF0dGVyIGdldHMgdGhlIGRhdGEgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCB0byBgZmlyZWAgYW5kIGFkZGl0aW9uYWxseSBgdGFyZ2V0YCBhbmQgYHR5cGVgIHByb3BlcnRpZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbjogZnVuY3Rpb24odHlwZSwgZm4pIHtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSB0aGlzLl9ldmVudHNbdHlwZV0gfHwgW107XG4gICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGZuKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgZXZlbnQgbGlzdGVuZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBbdHlwZV0gRXZlbnQgdHlwZS4gSWYgbm9uZSBpcyBzcGVjaWZpZWQsIHJlbW92ZSBhbGwgbGlzdGVuZXJzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2xpc3RlbmVyXSBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQuIElmIG5vbmUgaXMgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgYXJlIHJlbW92ZWRcbiAgICAgKi9cbiAgICBvZmY6IGZ1bmN0aW9uKHR5cGUsIGZuKSB7XG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgICAgLy8gY2xlYXIgYWxsIGxpc3RlbmVycyBpZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMubGlzdGVucyh0eXBlKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGZuKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gdGhpcy5fZXZlbnRzW3R5cGVdLmluZGV4T2YoZm4pO1xuICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbCBhIGZ1bmN0aW9uIG9uY2Ugd2hlbiBhbiBldmVudCBoYXMgZmlyZWRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uY2Ugd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbmNlOiBmdW5jdGlvbih0eXBlLCBmbikge1xuICAgICAgICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMub2ZmKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICAgICAgZm4uY2FsbCh0aGlzLCBkYXRhKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLm9uKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRmlyZSBldmVudCBvZiBhIGdpdmVuIHN0cmluZyB0eXBlIHdpdGggdGhlIGdpdmVuIGRhdGEgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXZlbnQgbmFtZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV0gT3B0aW9uYWwgZGF0YSBwYXNzZWQgZG93biB0byB0aGUgZXZlbnQgb2JqZWN0XG4gICAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgb2JqZWN0IGxpc3RlbnMgdG8gYW4gZXZlbnQgb2YgYSBwYXJ0aWN1bGFyIHR5cGVcbiAgICAgKi9cbiAgICBmaXJlOiBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBkYXRhID0gdXRpbC5leHRlbmQoe30sIGRhdGEpO1xuICAgICAgICB1dGlsLmV4dGVuZChkYXRhLCB7dHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzfSk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmNhbGwodGhpcywgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYW4gZXZlbnQgaXMgcmVnaXN0ZXJlZCB0byBhIHR5cGVcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBvYmplY3QgbGlzdGVucyB0byBhbiBldmVudCBvZiBhIHBhcnRpY3VsYXIgdHlwZVxuICAgICAqL1xuICAgIGxpc3RlbnM6IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICEhKHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbdHlwZV0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRlZDtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaHM7XG5cbmZ1bmN0aW9uIEdseXBocyhwYmYsIGVuZCkge1xuICAgIHRoaXMuc3RhY2tzID0gcGJmLnJlYWRGaWVsZHMocmVhZEZvbnRzdGFja3MsIFtdLCBlbmQpO1xufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrcyh0YWcsIHN0YWNrcywgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkge1xuICAgICAgICB2YXIgZm9udHN0YWNrID0gcGJmLnJlYWRNZXNzYWdlKHJlYWRGb250c3RhY2ssIHtnbHlwaHM6IHt9fSk7XG4gICAgICAgIHN0YWNrcy5wdXNoKGZvbnRzdGFjayk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrKHRhZywgZm9udHN0YWNrLCBwYmYpIHtcbiAgICBpZiAodGFnID09PSAxKSBmb250c3RhY2submFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSAyKSBmb250c3RhY2sucmFuZ2UgPSBwYmYucmVhZFN0cmluZygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykge1xuICAgICAgICB2YXIgZ2x5cGggPSBwYmYucmVhZE1lc3NhZ2UocmVhZEdseXBoLCB7fSk7XG4gICAgICAgIGZvbnRzdGFjay5nbHlwaHNbZ2x5cGguaWRdID0gZ2x5cGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkR2x5cGgodGFnLCBnbHlwaCwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkgZ2x5cGguaWQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgZ2x5cGguYml0bWFwID0gcGJmLnJlYWRCeXRlcygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykgZ2x5cGgud2lkdGggPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgZ2x5cGguaGVpZ2h0ID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDUpIGdseXBoLmxlZnQgPSBwYmYucmVhZFNWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDYpIGdseXBoLnRvcCA9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNykgZ2x5cGguYWR2YW5jZSA9IHBiZi5yZWFkVmFyaW50KCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGU7XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKGEsIGIsIHQpIHtcbiAgICByZXR1cm4gKGEgKiAoMSAtIHQpKSArIChiICogdCk7XG59XG5cbmludGVycG9sYXRlLm51bWJlciA9IGludGVycG9sYXRlO1xuXG5pbnRlcnBvbGF0ZS52ZWMyID0gZnVuY3Rpb24oZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMV0sIHRvWzFdLCB0KVxuICAgIF07XG59O1xuXG4vKlxuICogSW50ZXJwb2xhdGUgYmV0d2VlbiB0d28gY29sb3JzIGdpdmVuIGFzIDQtZWxlbWVudCBhcnJheXMuXG4gKlxuICogQHBhcmFtIHtDb2xvcn0gZnJvbVxuICogQHBhcmFtIHtDb2xvcn0gdG9cbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gZmFjdG9yIGJldHdlZW4gMCBhbmQgMVxuICogQHJldHVybnMge0NvbG9yfSBpbnRlcnBvbGF0ZWQgY29sb3JcbiAqL1xuaW50ZXJwb2xhdGUuY29sb3IgPSBmdW5jdGlvbihmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMF0sIHRvWzBdLCB0KSxcbiAgICAgICAgaW50ZXJwb2xhdGUoZnJvbVsxXSwgdG9bMV0sIHQpLFxuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzJdLCB0b1syXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bM10sIHRvWzNdLCB0KVxuICAgIF07XG59O1xuXG5pbnRlcnBvbGF0ZS5hcnJheSA9IGZ1bmN0aW9uKGZyb20sIHRvLCB0KSB7XG4gICAgcmV0dXJuIGZyb20ubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlKGQsIHRvW2ldLCB0KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuL2Jyb3dzZXInKTtcblxuZnVuY3Rpb24gbm9ybWFsaXplVVJMKHVybCwgcGF0aFByZWZpeCwgYWNjZXNzVG9rZW4pIHtcbiAgICBhY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuIHx8IGNvbmZpZy5BQ0NFU1NfVE9LRU47XG5cbiAgICBpZiAoIWFjY2Vzc1Rva2VuICYmIGNvbmZpZy5SRVFVSVJFX0FDQ0VTU19UT0tFTikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FuIEFQSSBhY2Nlc3MgdG9rZW4gaXMgcmVxdWlyZWQgdG8gdXNlIE1hcGJveCBHTC4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZGV2ZWxvcGVycy9hcGkvI2FjY2Vzcy10b2tlbnMnKTtcbiAgICB9XG5cbiAgICB2YXIgaHR0cHMgPSBjb25maWcuRk9SQ0VfSFRUUFMgfHxcbiAgICAgICAgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonKTtcblxuICAgIHVybCA9IHVybC5yZXBsYWNlKC9ebWFwYm94OlxcL1xcLy8sIChodHRwcyA/IGNvbmZpZy5IVFRQU19VUkwgOiBjb25maWcuSFRUUF9VUkwpICsgcGF0aFByZWZpeCk7XG4gICAgdXJsICs9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyZhY2Nlc3NfdG9rZW49JyA6ICc/YWNjZXNzX3Rva2VuPSc7XG5cbiAgICBpZiAoY29uZmlnLlJFUVVJUkVfQUNDRVNTX1RPS0VOKSB7XG4gICAgICAgIGlmIChhY2Nlc3NUb2tlblswXSA9PT0gJ3MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VzZSBhIHB1YmxpYyBhY2Nlc3MgdG9rZW4gKHBrLiopIHdpdGggTWFwYm94IEdMIEpTLCBub3QgYSBzZWNyZXQgYWNjZXNzIHRva2VuIChzay4qKS4gJyArXG4gICAgICAgICAgICAgICAgJ1NlZSBodHRwczovL3d3dy5tYXBib3guY29tL2RldmVsb3BlcnMvYXBpLyNhY2Nlc3MtdG9rZW5zJyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cmwgKz0gYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybDtcbn1cblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU3R5bGVVUkwgPSBmdW5jdGlvbih1cmwsIGFjY2Vzc1Rva2VuKSB7XG4gICAgdmFyIHVzZXIgPSB1cmwubWF0Y2goL15tYXBib3g6XFwvXFwvKFteLl0rKS8pO1xuICAgIGlmICghdXNlcilcbiAgICAgICAgcmV0dXJuIHVybDtcblxuICAgIHJldHVybiBub3JtYWxpemVVUkwodXJsLCAnL3N0eWxlcy92MS8nICsgdXNlclsxXSArICcvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU291cmNlVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgdXJsID0gbm9ybWFsaXplVVJMKHVybCArICcuanNvbicsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xuXG4gICAgLy8gVGlsZUpTT04gcmVxdWVzdHMgbmVlZCBhIHNlY3VyZSBmbGFnIGFwcGVuZGVkIHRvIHRoZWlyIFVSTHMgc29cbiAgICAvLyB0aGF0IHRoZSBzZXJ2ZXIga25vd3MgdG8gc2VuZCBTU0wtaWZpZWQgcmVzb3VyY2UgcmVmZXJlbmNlcy5cbiAgICBpZiAodXJsLmluZGV4T2YoJ2h0dHBzJykgPT09IDApXG4gICAgICAgIHVybCArPSAnJnNlY3VyZSc7XG5cbiAgICByZXR1cm4gdXJsO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplR2x5cGhzVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZVVSTCh1cmwsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplVGlsZVVSTCA9IGZ1bmN0aW9uKHVybCwgc291cmNlVXJsKSB7XG4gICAgaWYgKCFzb3VyY2VVcmwgfHwgIXNvdXJjZVVybC5tYXRjaCgvXm1hcGJveDpcXC9cXC8vKSlcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICByZXR1cm4gdXJsLnJlcGxhY2UoL1xcLigoPzpwbmd8anBnKVxcZCopKD89JHxcXD8pLywgYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID49IDIgPyAnQDJ4LiQxJyA6ICcuJDEnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBBIFttb3N0LXJlY2VudGx5LXVzZWQgY2FjaGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FjaGVfYWxnb3JpdGhtcylcbiAqIHdpdGggaGFzaCBsb29rdXAgbWFkZSBwb3NzaWJsZSBieSBrZWVwaW5nIGEgbGlzdCBvZiBrZXlzIGluIHBhcmFsbGVsIHRvXG4gKiBhbiBhcnJheSBvZiBkaWN0aW9uYXJ5IG9mIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXggbnVtYmVyIG9mIHBlcm1pdHRlZCB2YWx1ZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVtb3ZlIGNhbGxiYWNrIGNhbGxlZCB3aXRoIGl0ZW1zIHdoZW4gdGhleSBleHBpcmVcbiAqIEBwcml2YXRlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gTVJVQ2FjaGU7XG5mdW5jdGlvbiBNUlVDYWNoZShtYXgsIG9uUmVtb3ZlKSB7XG4gICAgdGhpcy5tYXggPSBtYXg7XG4gICAgdGhpcy5vblJlbW92ZSA9IG9uUmVtb3ZlO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cblxuLyoqXG4gKiBDbGVhciB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7TVJVQ2FjaGV9IHRoaXMgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMubGlzdCkge1xuICAgICAgICB0aGlzLm9uUmVtb3ZlKHRoaXMubGlzdFtrZXldKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpc3QgPSB7fTtcbiAgICB0aGlzLm9yZGVyID0gW107XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBBZGQgYSBrZXksIHZhbHVlIGNvbWJpbmF0aW9uIHRvIHRoZSBjYWNoZSwgdHJpbW1pbmcgaXRzIHNpemUgaWYgdGhpcyBwdXNoZXNcbiAqIGl0IG92ZXIgbWF4IGxlbmd0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IGxvb2t1cCBrZXkgZm9yIHRoZSBpdGVtXG4gKiBAcGFyYW0geyp9IGRhdGEgYW55IHZhbHVlXG4gKlxuICogQHJldHVybnMge01SVUNhY2hlfSB0aGlzIGNhY2hlXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB0aGlzLmxpc3Rba2V5XSA9IGRhdGE7XG4gICAgdGhpcy5vcmRlci5wdXNoKGtleSk7XG5cbiAgICBpZiAodGhpcy5vcmRlci5sZW5ndGggPiB0aGlzLm1heCkge1xuICAgICAgICB2YXIgcmVtb3ZlZERhdGEgPSB0aGlzLmdldCh0aGlzLm9yZGVyWzBdKTtcbiAgICAgICAgaWYgKHJlbW92ZWREYXRhKSB0aGlzLm9uUmVtb3ZlKHJlbW92ZWREYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYGtleWAgaXMgcHJlc2VudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBiZSBsb29rZWQtdXBcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIHRoZSBjYWNoZSBoYXMgdGhpcyB2YWx1ZVxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmxpc3Q7XG59O1xuXG4vKlxuICogTGlzdCBhbGwga2V5cyBpbiB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gYW4gYXJyYXkgb2Yga2V5cyBpbiB0aGlzIGNhY2hlLlxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm9yZGVyO1xufTtcblxuLypcbiAqIEdldCB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYSBzcGVjaWZpYyBrZXkuIElmIHRoZSBrZXkgaXMgbm90IGZvdW5kLFxuICogcmV0dXJucyBgbnVsbGBcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gbG9vayB1cFxuICogQHJldHVybnMgeyp9IHRoZSBkYXRhLCBvciBudWxsIGlmIGl0IGlzbid0IGZvdW5kXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsgcmV0dXJuIG51bGw7IH1cblxuICAgIHZhciBkYXRhID0gdGhpcy5saXN0W2tleV07XG5cbiAgICBkZWxldGUgdGhpcy5saXN0W2tleV07XG4gICAgdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGtleSksIDEpO1xuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUb2tlbnM7XG5cbi8qKlxuICogUmVwbGFjZSB0b2tlbnMgaW4gYSBzdHJpbmcgdGVtcGxhdGUgd2l0aCB2YWx1ZXMgaW4gYW4gb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgYSBrZXkvdmFsdWUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9rZW5zIGFuZCByZXBsYWNlbWVudHNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IHRoZSB0ZW1wbGF0ZSBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0ZW1wbGF0ZSB3aXRoIHRva2VucyByZXBsYWNlZFxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVRva2Vucyhwcm9wZXJ0aWVzLCB0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgveyhbXnt9KClcXFtcXF08PiQ9OjsuLF5dKyl9L2csIGZ1bmN0aW9uKG1hdGNoLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSBpbiBwcm9wZXJ0aWVzID8gcHJvcGVydGllc1trZXldIDogJyc7XG4gICAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBVbml0QmV6aWVyID0gcmVxdWlyZSgndW5pdGJlemllcicpO1xuXG4vKipcbiAqIEdpdmVuIGEgdmFsdWUgYHRgIHRoYXQgdmFyaWVzIGJldHdlZW4gMCBhbmQgMSwgcmV0dXJuXG4gKiBhbiBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uIHRoYXQgZWFzZXMgYmV0d2VlbiAwIGFuZCAxIGluIGEgcGxlYXNpbmdcbiAqIGN1YmljIGluLW91dCBmYXNoaW9uLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IGlucHV0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBpbnB1dFxuICovXG5leHBvcnRzLmVhc2VDdWJpY0luT3V0ID0gZnVuY3Rpb24gKHQpIHtcbiAgICBpZiAodCA8PSAwKSByZXR1cm4gMDtcbiAgICBpZiAodCA+PSAxKSByZXR1cm4gMTtcbiAgICB2YXIgdDIgPSB0ICogdCxcbiAgICAgICAgdDMgPSB0MiAqIHQ7XG4gICAgcmV0dXJuIDQgKiAodCA8IDAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAwLjc1KTtcbn07XG5cbi8qKlxuICogR2l2ZW4gZ2l2ZW4gKHgsIHkpLCAoeDEsIHkxKSBjb250cm9sIHBvaW50cyBmb3IgYSBiZXppZXIgY3VydmUsXG4gKiByZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGludGVycG9sYXRlcyBhbG9uZyB0aGF0IGN1cnZlLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMXggY29udHJvbCBwb2ludCAxIHggY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHAxeSBjb250cm9sIHBvaW50IDEgeSBjb29yZGluYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gcDJ4IGNvbnRyb2wgcG9pbnQgMiB4IGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMnkgY29udHJvbCBwb2ludCAyIHkgY29vcmRpbmF0ZVxuICogQHJldHVybnMge0Z1bmN0aW9ufSBpbnRlcnBvbGF0b3I6IHJlY2VpdmVzIG51bWJlciB2YWx1ZSwgcmV0dXJuc1xuICogbnVtYmVyIHZhbHVlLlxuICovXG5leHBvcnRzLmJlemllciA9IGZ1bmN0aW9uKHAxeCwgcDF5LCBwMngsIHAyeSkge1xuICAgIHZhciBiZXppZXIgPSBuZXcgVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiBiZXppZXIuc29sdmUodCk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogQSBkZWZhdWx0IGJlemllci1jdXJ2ZSBwb3dlcmVkIGVhc2luZyBmdW5jdGlvbiB3aXRoXG4gKiBjb250cm9sIHBvaW50cyAoMC4yNSwgMC4xKSBhbmQgKDAuMjUsIDEpXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IG91dHB1dFxuICovXG5leHBvcnRzLmVhc2UgPSBleHBvcnRzLmJlemllcigwLjI1LCAwLjEsIDAuMjUsIDEpO1xuXG4vKipcbiAqIEdpdmVuIGEgZm91ci1lbGVtZW50IGFycmF5IG9mIG51bWJlcnMgdGhhdCByZXByZXNlbnRzIGEgY29sb3IgaW5cbiAqIFJHQkEsIHJldHVybiBhIHZlcnNpb24gZm9yIHdoaWNoIHRoZSBSR0IgY29tcG9uZW50cyBhcmUgbXVsdGlwbGllZFxuICogYnkgdGhlIEEgKGFscGhhKSBjb21wb25lbnRcbiAqXG4gKiBAcGFyYW0ge051bWJlcjxBcnJheT59IGMgY29sb3IgYXJyYXlcbiAqIEByZXR1cm5zIHtOdW1iZXI8QXJyYXk+fSBwcmVtdWx0aXBsaWVkIGNvbG9yIGFycmF5XG4gKi9cbmV4cG9ydHMucHJlbXVsdGlwbHkgPSBmdW5jdGlvbiAoYykge1xuICAgIGNbMF0gKj0gY1szXTtcbiAgICBjWzFdICo9IGNbM107XG4gICAgY1syXSAqPSBjWzNdO1xuICAgIHJldHVybiBjO1xufTtcblxuLyoqXG4gKiBjb25zdHJhaW4gbiB0byB0aGUgZ2l2ZW4gcmFuZ2UgdmlhIG1pbiArIG1heFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuIHZhbHVlXG4gKiBAcGFyYW0ge051bWJlcn0gbWluIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4IHRoZSBtYXhpbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcmV0dXJucyB7TnVtYmVyfSB0aGUgY2xhbXBlZCB2YWx1ZVxuICovXG5leHBvcnRzLmNsYW1wID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCBuKSk7XG59O1xuXG4vKlxuICogY29uc3RyYWluIG4gdG8gdGhlIGdpdmVuIHJhbmdlIHZpYSBtb2R1bGFyIGFyaXRobWV0aWNcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcGFyYW0ge051bWJlcn0gbWluXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBjb25zdHJhaW5lZCBudW1iZXJcbiAqL1xuZXhwb3J0cy53cmFwID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgcmV0dXJuIG4gPT09IG1heCA/IG4gOiAoKG4gLSBtaW4pICUgZCArIGQpICUgZCArIG1pbjtcbn07XG5cbi8qXG4gKiByZXR1cm4gdGhlIGZpcnN0IG5vbi1udWxsIGFuZCBub24tdW5kZWZpbmVkIGFyZ3VtZW50IHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7Kn0gYXJndW1lbnRcbiAqL1xuZXhwb3J0cy5jb2FsZXNjZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGlmIChhcmcgIT09IG51bGwgJiYgYXJnICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gYXJnO1xuICAgIH1cbn07XG5cbi8qXG4gKiBDYWxsIGFuIGFzeW5jaHJvbm91cyBmdW5jdGlvbiBvbiBhbiBhcnJheSBvZiBhcmd1bWVudHMsXG4gKiBjYWxsaW5nIGBjYWxsYmFja2Agb25jZSBhbGwgY2FsbHMgY29tcGxldGUuXG4gKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyYXkgaW5wdXQgdG8gZWFjaCBjYWxsIG9mIHRoZSBhc3luYyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIGFuIGFzeW5jIGZ1bmN0aW9uIHdpdGggc2lnbmF0dXJlIChkYXRhLCBjYWxsYmFjaylcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgY2FsbGJhY2sgcnVuIGFmdGVyIGFsbCBhc3luYyB3b3JrIGlzIGRvbmUuXG4gKiBjYWxsZWQgd2l0aCBubyBhcmd1bWVudHNcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydHMuYXN5bmNFYWNoID0gZnVuY3Rpb24gKGFycmF5LCBmbiwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVtYWluaW5nID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChyZW1haW5pbmcgPT09IDApIHJldHVybiBjYWxsYmFjaygpO1xuICAgIGZ1bmN0aW9uIGNoZWNrKCkgeyBpZiAoLS1yZW1haW5pbmcgPT09IDApIGNhbGxiYWNrKCk7IH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBmbihhcnJheVtpXSwgY2hlY2spO1xufTtcblxuLypcbiAqIENvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUga2V5cyBpbiBvbmUgb2JqZWN0IGFuZCB0aGUga2V5c1xuICogaW4gYW5vdGhlciBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0ga2V5cyBkaWZmZXJlbmNlXG4gKi9cbmV4cG9ydHMua2V5c0RpZmZlcmVuY2UgPSBmdW5jdGlvbiAob2JqLCBvdGhlcikge1xuICAgIHZhciBkaWZmZXJlbmNlID0gW107XG4gICAgZm9yICh2YXIgaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKCEoaSBpbiBvdGhlcikpIHtcbiAgICAgICAgICAgIGRpZmZlcmVuY2UucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGlmZmVyZW5jZTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYSBkZXN0aW5hdGlvbiBvYmplY3QgYW5kIG9wdGlvbmFsbHkgbWFueSBzb3VyY2Ugb2JqZWN0cyxcbiAqIGNvcHkgYWxsIHByb3BlcnRpZXMgZnJvbSB0aGUgc291cmNlIG9iamVjdHMgaW50byB0aGUgZGVzdGluYXRpb24uXG4gKiBUaGUgbGFzdCBzb3VyY2Ugb2JqZWN0IGdpdmVuIG92ZXJyaWRlcyBwcm9wZXJ0aWVzIGZyb20gcHJldmlvdXNcbiAqIHNvdXJjZSBvYmplY3RzLlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3QgZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBzb3VyY2VzIGZyb20gd2hpY2ggcHJvcGVydGllcyBhcmUgcHVsbGVkXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBkZXN0XG4gKi9cbmV4cG9ydHMuZXh0ZW5kID0gZnVuY3Rpb24gKGRlc3QpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3JjID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrIGluIHNyYykge1xuICAgICAgICAgICAgZGVzdFtrXSA9IHNyY1trXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn07XG5cbi8qKlxuICogRXh0ZW5kIGEgZGVzdGluYXRpb24gb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb2YgdGhlIHNyYyBvYmplY3QsXG4gKiB1c2luZyBkZWZpbmVQcm9wZXJ0eSBpbnN0ZWFkIG9mIHNpbXBsZSBhc3NpZ25tZW50LlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBzcmNcbiAqIEByZXR1cm5zIHtPYmplY3R9IGRlc3RcbiAqL1xuZXhwb3J0cy5leHRlbmRBbGwgPSBmdW5jdGlvbiAoZGVzdCwgc3JjKSB7XG4gICAgZm9yICh2YXIgaSBpbiBzcmMpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIGksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc3JjLCBpKSk7XG4gICAgfVxuICAgIHJldHVybiBkZXN0O1xufTtcblxuLyoqXG4gKiBFeHRlbmQgYSBwYXJlbnQncyBwcm90b3R5cGUgd2l0aCBhbGwgcHJvcGVydGllcyBpbiBhIHByb3BlcnRpZXNcbiAqIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyZW50XG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAqIEByZXR1cm5zIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuaW5oZXJpdCA9IGZ1bmN0aW9uIChwYXJlbnQsIHByb3BzKSB7XG4gICAgdmFyIHBhcmVudFByb3RvID0gdHlwZW9mIHBhcmVudCA9PT0gJ2Z1bmN0aW9uJyA/IHBhcmVudC5wcm90b3R5cGUgOiBwYXJlbnQsXG4gICAgICAgIHByb3RvID0gT2JqZWN0LmNyZWF0ZShwYXJlbnRQcm90byk7XG4gICAgZXhwb3J0cy5leHRlbmRBbGwocHJvdG8sIHByb3BzKTtcbiAgICByZXR1cm4gcHJvdG87XG59O1xuXG4vKipcbiAqIEdpdmVuIGFuIG9iamVjdCBhbmQgYSBudW1iZXIgb2YgcHJvcGVydGllcyBhcyBzdHJpbmdzLCByZXR1cm4gdmVyc2lvblxuICogb2YgdGhhdCBvYmplY3Qgd2l0aCBvbmx5IHRob3NlIHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNyYyB0aGUgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IHByb3BlcnRpZXMgYW4gYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgY2hvc2VuXG4gKiB0byBhcHBlYXIgb24gdGhlIHJlc3VsdGluZyBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3Qgd2l0aCBsaW1pdGVkIHByb3BlcnRpZXMuXG4gKiBAZXhhbXBsZVxuICogdmFyIGZvbyA9IHsgbmFtZTogJ0NoYXJsaWUnLCBhZ2U6IDEwIH07XG4gKiB2YXIganVzdE5hbWUgPSBwaWNrKGZvbywgWyduYW1lJ10pO1xuICogLy8ganVzdE5hbWUgPSB7IG5hbWU6ICdDaGFybGllJyB9XG4gKi9cbmV4cG9ydHMucGljayA9IGZ1bmN0aW9uIChzcmMsIHByb3BlcnRpZXMpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgaWYgKGsgaW4gc3JjKSB7XG4gICAgICAgICAgICByZXN1bHRba10gPSBzcmNba107XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbnZhciBpZCA9IDE7XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pcXVlIG51bWVyaWMgaWQsIHN0YXJ0aW5nIGF0IDEgYW5kIGluY3JlbWVudGluZyB3aXRoXG4gKiBlYWNoIGNhbGwuXG4gKlxuICogQHJldHVybnMge051bWJlcn0gdW5pcXVlIG51bWVyaWMgaWQuXG4gKi9cbmV4cG9ydHMudW5pcXVlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGlkKys7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIHZlcnNpb24gb2YgYGZuYCB0aGF0IG9ubHkgZmlyZXMgb25jZSBldmVyeSBgdGltZWAgbWlsbHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gdGhlIGZ1bmN0aW9uIHRvIGJlIHRocm90dGxlZFxuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWUgbWlsbHNlY29uZHMgcmVxdWlyZWQgYmV0d2VlbiBmdW5jdGlvbiBjYWxsc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSB2YWx1ZSBvZiBgdGhpc2Agd2l0aCB3aGljaCB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IGRlYm91bmNlZCBmdW5jdGlvblxuICovXG5leHBvcnRzLnRocm90dGxlID0gZnVuY3Rpb24gKGZuLCB0aW1lLCBjb250ZXh0KSB7XG4gICAgdmFyIGxvY2ssIGFyZ3MsIHdyYXBwZXJGbiwgbGF0ZXI7XG5cbiAgICBsYXRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcbiAgICAgICAgbG9jayA9IGZhbHNlO1xuICAgICAgICBpZiAoYXJncykge1xuICAgICAgICAgICAgd3JhcHBlckZuLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgYXJncyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdyYXBwZXJGbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGxvY2spIHtcbiAgICAgICAgICAgIC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxuICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY2FsbCBhbmQgbG9jayB1bnRpbCBsYXRlclxuICAgICAgICAgICAgZm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xuICAgICAgICAgICAgbG9jayA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHdyYXBwZXJGbjtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgdmVyc2lvbiBvZiBgZm5gIHRoYXQgaXMgb25seSBjYWxsZWQgYHRpbWVgIG1pbGxpc2Vjb25kc1xuICogYWZ0ZXIgaXRzIGxhc3QgaW52b2NhdGlvblxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIHRoZSBmdW5jdGlvbiB0byBiZSBkZWJvdW5jZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lIG1pbGxzZWNvbmRzIGFmdGVyIHdoaWNoIHRoZSBmdW5jdGlvbiB3aWxsIGJlIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZGVib3VuY2VkIGZ1bmN0aW9uXG4gKi9cbmV4cG9ydHMuZGVib3VuY2UgPSBmdW5jdGlvbihmbiwgdGltZSkge1xuICAgIHZhciB0aW1lciwgYXJncztcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcblxuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgfSwgdGltZSk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYW4gYXJyYXkgb2YgbWVtYmVyIGZ1bmN0aW9uIG5hbWVzIGFzIHN0cmluZ3MsIHJlcGxhY2UgYWxsIG9mIHRoZW1cbiAqIHdpdGggYm91bmQgdmVyc2lvbnMgdGhhdCB3aWxsIGFsd2F5cyByZWZlciB0byBgY29udGV4dGAgYXMgYHRoaXNgLiBUaGlzXG4gKiBpcyB1c2VmdWwgZm9yIGNsYXNzZXMgd2hlcmUgb3RoZXJ3aXNlIGV2ZW50IGJpbmRpbmdzIHdvdWxkIHJlYXNzaWduXG4gKiBgdGhpc2AgdG8gdGhlIGV2ZW50ZWQgb2JqZWN0IG9yIHNvbWUgb3RoZXIgdmFsdWU6IHRoaXMgbGV0cyB5b3UgZW5zdXJlXG4gKiB0aGUgYHRoaXNgIHZhbHVlIGFsd2F5cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGZucyBsaXN0IG9mIG1lbWJlciBmdW5jdGlvbiBuYW1lc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSBjb250ZXh0IHZhbHVlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBjaGFuZ2VzIGZ1bmN0aW9ucyBpbi1wbGFjZVxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIE15Q2xhc3MoKSB7XG4gKiAgIGJpbmRBbGwoWydvbnRpbWVyJ10sIHRoaXMpO1xuICogICB0aGlzLm5hbWUgPSAnVG9tJztcbiAqIH1cbiAqIE15Q2xhc3MucHJvdG90eXBlLm9udGltZXIgPSBmdW5jdGlvbigpIHtcbiAqICAgYWxlcnQodGhpcy5uYW1lKTtcbiAqIH07XG4gKiB2YXIgbXlDbGFzcyA9IG5ldyBNeUNsYXNzKCk7XG4gKiBzZXRUaW1lb3V0KG15Q2xhc3Mub250aW1lciwgMTAwKTtcbiAqL1xuZXhwb3J0cy5iaW5kQWxsID0gZnVuY3Rpb24oZm5zLCBjb250ZXh0KSB7XG4gICAgZm5zLmZvckVhY2goZnVuY3Rpb24oZm4pIHtcbiAgICAgICAgY29udGV4dFtmbl0gPSBjb250ZXh0W2ZuXS5iaW5kKGNvbnRleHQpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlICdvcHRpb25zJyBwcm9wZXJ0eSBvbiBgb2JqYCB3aXRoIHByb3BlcnRpZXNcbiAqIGZyb20gdGhlIGBvcHRpb25zYCBhcmd1bWVudC4gUHJvcGVydGllcyBpbiB0aGUgYG9wdGlvbnNgXG4gKiBvYmplY3Qgd2lsbCBvdmVycmlkZSBleGlzdGluZyBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvYmplY3Qgb2Ygb3ZlcnJpZGUgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gZGVyaXZlZCBvcHRpb25zIG9iamVjdC5cbiAqL1xuZXhwb3J0cy5zZXRPcHRpb25zID0gZnVuY3Rpb24ob2JqLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSkge1xuICAgICAgICBvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gT2JqZWN0LmNyZWF0ZShvYmoub3B0aW9ucykgOiB7fTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XG4gICAgICAgIG9iai5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG9iai5vcHRpb25zO1xufTtcbiIsIi8vIChjKSBEZWFuIE1jTmFtZWUgPGRlYW5AZ21haWwuY29tPiwgMjAxMi5cbi8vXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZGVhbm0vY3NzLWNvbG9yLXBhcnNlci1qc1xuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4vLyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4vLyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtY29sb3IvXG52YXIga0NTU0NvbG9yVGFibGUgPSB7XG4gIFwidHJhbnNwYXJlbnRcIjogWzAsMCwwLDBdLCBcImFsaWNlYmx1ZVwiOiBbMjQwLDI0OCwyNTUsMV0sXG4gIFwiYW50aXF1ZXdoaXRlXCI6IFsyNTAsMjM1LDIxNSwxXSwgXCJhcXVhXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiYXF1YW1hcmluZVwiOiBbMTI3LDI1NSwyMTIsMV0sIFwiYXp1cmVcIjogWzI0MCwyNTUsMjU1LDFdLFxuICBcImJlaWdlXCI6IFsyNDUsMjQ1LDIyMCwxXSwgXCJiaXNxdWVcIjogWzI1NSwyMjgsMTk2LDFdLFxuICBcImJsYWNrXCI6IFswLDAsMCwxXSwgXCJibGFuY2hlZGFsbW9uZFwiOiBbMjU1LDIzNSwyMDUsMV0sXG4gIFwiYmx1ZVwiOiBbMCwwLDI1NSwxXSwgXCJibHVldmlvbGV0XCI6IFsxMzgsNDMsMjI2LDFdLFxuICBcImJyb3duXCI6IFsxNjUsNDIsNDIsMV0sIFwiYnVybHl3b29kXCI6IFsyMjIsMTg0LDEzNSwxXSxcbiAgXCJjYWRldGJsdWVcIjogWzk1LDE1OCwxNjAsMV0sIFwiY2hhcnRyZXVzZVwiOiBbMTI3LDI1NSwwLDFdLFxuICBcImNob2NvbGF0ZVwiOiBbMjEwLDEwNSwzMCwxXSwgXCJjb3JhbFwiOiBbMjU1LDEyNyw4MCwxXSxcbiAgXCJjb3JuZmxvd2VyYmx1ZVwiOiBbMTAwLDE0OSwyMzcsMV0sIFwiY29ybnNpbGtcIjogWzI1NSwyNDgsMjIwLDFdLFxuICBcImNyaW1zb25cIjogWzIyMCwyMCw2MCwxXSwgXCJjeWFuXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiZGFya2JsdWVcIjogWzAsMCwxMzksMV0sIFwiZGFya2N5YW5cIjogWzAsMTM5LDEzOSwxXSxcbiAgXCJkYXJrZ29sZGVucm9kXCI6IFsxODQsMTM0LDExLDFdLCBcImRhcmtncmF5XCI6IFsxNjksMTY5LDE2OSwxXSxcbiAgXCJkYXJrZ3JlZW5cIjogWzAsMTAwLDAsMV0sIFwiZGFya2dyZXlcIjogWzE2OSwxNjksMTY5LDFdLFxuICBcImRhcmtraGFraVwiOiBbMTg5LDE4MywxMDcsMV0sIFwiZGFya21hZ2VudGFcIjogWzEzOSwwLDEzOSwxXSxcbiAgXCJkYXJrb2xpdmVncmVlblwiOiBbODUsMTA3LDQ3LDFdLCBcImRhcmtvcmFuZ2VcIjogWzI1NSwxNDAsMCwxXSxcbiAgXCJkYXJrb3JjaGlkXCI6IFsxNTMsNTAsMjA0LDFdLCBcImRhcmtyZWRcIjogWzEzOSwwLDAsMV0sXG4gIFwiZGFya3NhbG1vblwiOiBbMjMzLDE1MCwxMjIsMV0sIFwiZGFya3NlYWdyZWVuXCI6IFsxNDMsMTg4LDE0MywxXSxcbiAgXCJkYXJrc2xhdGVibHVlXCI6IFs3Miw2MSwxMzksMV0sIFwiZGFya3NsYXRlZ3JheVwiOiBbNDcsNzksNzksMV0sXG4gIFwiZGFya3NsYXRlZ3JleVwiOiBbNDcsNzksNzksMV0sIFwiZGFya3R1cnF1b2lzZVwiOiBbMCwyMDYsMjA5LDFdLFxuICBcImRhcmt2aW9sZXRcIjogWzE0OCwwLDIxMSwxXSwgXCJkZWVwcGlua1wiOiBbMjU1LDIwLDE0NywxXSxcbiAgXCJkZWVwc2t5Ymx1ZVwiOiBbMCwxOTEsMjU1LDFdLCBcImRpbWdyYXlcIjogWzEwNSwxMDUsMTA1LDFdLFxuICBcImRpbWdyZXlcIjogWzEwNSwxMDUsMTA1LDFdLCBcImRvZGdlcmJsdWVcIjogWzMwLDE0NCwyNTUsMV0sXG4gIFwiZmlyZWJyaWNrXCI6IFsxNzgsMzQsMzQsMV0sIFwiZmxvcmFsd2hpdGVcIjogWzI1NSwyNTAsMjQwLDFdLFxuICBcImZvcmVzdGdyZWVuXCI6IFszNCwxMzksMzQsMV0sIFwiZnVjaHNpYVwiOiBbMjU1LDAsMjU1LDFdLFxuICBcImdhaW5zYm9yb1wiOiBbMjIwLDIyMCwyMjAsMV0sIFwiZ2hvc3R3aGl0ZVwiOiBbMjQ4LDI0OCwyNTUsMV0sXG4gIFwiZ29sZFwiOiBbMjU1LDIxNSwwLDFdLCBcImdvbGRlbnJvZFwiOiBbMjE4LDE2NSwzMiwxXSxcbiAgXCJncmF5XCI6IFsxMjgsMTI4LDEyOCwxXSwgXCJncmVlblwiOiBbMCwxMjgsMCwxXSxcbiAgXCJncmVlbnllbGxvd1wiOiBbMTczLDI1NSw0NywxXSwgXCJncmV5XCI6IFsxMjgsMTI4LDEyOCwxXSxcbiAgXCJob25leWRld1wiOiBbMjQwLDI1NSwyNDAsMV0sIFwiaG90cGlua1wiOiBbMjU1LDEwNSwxODAsMV0sXG4gIFwiaW5kaWFucmVkXCI6IFsyMDUsOTIsOTIsMV0sIFwiaW5kaWdvXCI6IFs3NSwwLDEzMCwxXSxcbiAgXCJpdm9yeVwiOiBbMjU1LDI1NSwyNDAsMV0sIFwia2hha2lcIjogWzI0MCwyMzAsMTQwLDFdLFxuICBcImxhdmVuZGVyXCI6IFsyMzAsMjMwLDI1MCwxXSwgXCJsYXZlbmRlcmJsdXNoXCI6IFsyNTUsMjQwLDI0NSwxXSxcbiAgXCJsYXduZ3JlZW5cIjogWzEyNCwyNTIsMCwxXSwgXCJsZW1vbmNoaWZmb25cIjogWzI1NSwyNTAsMjA1LDFdLFxuICBcImxpZ2h0Ymx1ZVwiOiBbMTczLDIxNiwyMzAsMV0sIFwibGlnaHRjb3JhbFwiOiBbMjQwLDEyOCwxMjgsMV0sXG4gIFwibGlnaHRjeWFuXCI6IFsyMjQsMjU1LDI1NSwxXSwgXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiOiBbMjUwLDI1MCwyMTAsMV0sXG4gIFwibGlnaHRncmF5XCI6IFsyMTEsMjExLDIxMSwxXSwgXCJsaWdodGdyZWVuXCI6IFsxNDQsMjM4LDE0NCwxXSxcbiAgXCJsaWdodGdyZXlcIjogWzIxMSwyMTEsMjExLDFdLCBcImxpZ2h0cGlua1wiOiBbMjU1LDE4MiwxOTMsMV0sXG4gIFwibGlnaHRzYWxtb25cIjogWzI1NSwxNjAsMTIyLDFdLCBcImxpZ2h0c2VhZ3JlZW5cIjogWzMyLDE3OCwxNzAsMV0sXG4gIFwibGlnaHRza3libHVlXCI6IFsxMzUsMjA2LDI1MCwxXSwgXCJsaWdodHNsYXRlZ3JheVwiOiBbMTE5LDEzNiwxNTMsMV0sXG4gIFwibGlnaHRzbGF0ZWdyZXlcIjogWzExOSwxMzYsMTUzLDFdLCBcImxpZ2h0c3RlZWxibHVlXCI6IFsxNzYsMTk2LDIyMiwxXSxcbiAgXCJsaWdodHllbGxvd1wiOiBbMjU1LDI1NSwyMjQsMV0sIFwibGltZVwiOiBbMCwyNTUsMCwxXSxcbiAgXCJsaW1lZ3JlZW5cIjogWzUwLDIwNSw1MCwxXSwgXCJsaW5lblwiOiBbMjUwLDI0MCwyMzAsMV0sXG4gIFwibWFnZW50YVwiOiBbMjU1LDAsMjU1LDFdLCBcIm1hcm9vblwiOiBbMTI4LDAsMCwxXSxcbiAgXCJtZWRpdW1hcXVhbWFyaW5lXCI6IFsxMDIsMjA1LDE3MCwxXSwgXCJtZWRpdW1ibHVlXCI6IFswLDAsMjA1LDFdLFxuICBcIm1lZGl1bW9yY2hpZFwiOiBbMTg2LDg1LDIxMSwxXSwgXCJtZWRpdW1wdXJwbGVcIjogWzE0NywxMTIsMjE5LDFdLFxuICBcIm1lZGl1bXNlYWdyZWVuXCI6IFs2MCwxNzksMTEzLDFdLCBcIm1lZGl1bXNsYXRlYmx1ZVwiOiBbMTIzLDEwNCwyMzgsMV0sXG4gIFwibWVkaXVtc3ByaW5nZ3JlZW5cIjogWzAsMjUwLDE1NCwxXSwgXCJtZWRpdW10dXJxdW9pc2VcIjogWzcyLDIwOSwyMDQsMV0sXG4gIFwibWVkaXVtdmlvbGV0cmVkXCI6IFsxOTksMjEsMTMzLDFdLCBcIm1pZG5pZ2h0Ymx1ZVwiOiBbMjUsMjUsMTEyLDFdLFxuICBcIm1pbnRjcmVhbVwiOiBbMjQ1LDI1NSwyNTAsMV0sIFwibWlzdHlyb3NlXCI6IFsyNTUsMjI4LDIyNSwxXSxcbiAgXCJtb2NjYXNpblwiOiBbMjU1LDIyOCwxODEsMV0sIFwibmF2YWpvd2hpdGVcIjogWzI1NSwyMjIsMTczLDFdLFxuICBcIm5hdnlcIjogWzAsMCwxMjgsMV0sIFwib2xkbGFjZVwiOiBbMjUzLDI0NSwyMzAsMV0sXG4gIFwib2xpdmVcIjogWzEyOCwxMjgsMCwxXSwgXCJvbGl2ZWRyYWJcIjogWzEwNywxNDIsMzUsMV0sXG4gIFwib3JhbmdlXCI6IFsyNTUsMTY1LDAsMV0sIFwib3JhbmdlcmVkXCI6IFsyNTUsNjksMCwxXSxcbiAgXCJvcmNoaWRcIjogWzIxOCwxMTIsMjE0LDFdLCBcInBhbGVnb2xkZW5yb2RcIjogWzIzOCwyMzIsMTcwLDFdLFxuICBcInBhbGVncmVlblwiOiBbMTUyLDI1MSwxNTIsMV0sIFwicGFsZXR1cnF1b2lzZVwiOiBbMTc1LDIzOCwyMzgsMV0sXG4gIFwicGFsZXZpb2xldHJlZFwiOiBbMjE5LDExMiwxNDcsMV0sIFwicGFwYXlhd2hpcFwiOiBbMjU1LDIzOSwyMTMsMV0sXG4gIFwicGVhY2hwdWZmXCI6IFsyNTUsMjE4LDE4NSwxXSwgXCJwZXJ1XCI6IFsyMDUsMTMzLDYzLDFdLFxuICBcInBpbmtcIjogWzI1NSwxOTIsMjAzLDFdLCBcInBsdW1cIjogWzIyMSwxNjAsMjIxLDFdLFxuICBcInBvd2RlcmJsdWVcIjogWzE3NiwyMjQsMjMwLDFdLCBcInB1cnBsZVwiOiBbMTI4LDAsMTI4LDFdLFxuICBcInJlZFwiOiBbMjU1LDAsMCwxXSwgXCJyb3N5YnJvd25cIjogWzE4OCwxNDMsMTQzLDFdLFxuICBcInJveWFsYmx1ZVwiOiBbNjUsMTA1LDIyNSwxXSwgXCJzYWRkbGVicm93blwiOiBbMTM5LDY5LDE5LDFdLFxuICBcInNhbG1vblwiOiBbMjUwLDEyOCwxMTQsMV0sIFwic2FuZHlicm93blwiOiBbMjQ0LDE2NCw5NiwxXSxcbiAgXCJzZWFncmVlblwiOiBbNDYsMTM5LDg3LDFdLCBcInNlYXNoZWxsXCI6IFsyNTUsMjQ1LDIzOCwxXSxcbiAgXCJzaWVubmFcIjogWzE2MCw4Miw0NSwxXSwgXCJzaWx2ZXJcIjogWzE5MiwxOTIsMTkyLDFdLFxuICBcInNreWJsdWVcIjogWzEzNSwyMDYsMjM1LDFdLCBcInNsYXRlYmx1ZVwiOiBbMTA2LDkwLDIwNSwxXSxcbiAgXCJzbGF0ZWdyYXlcIjogWzExMiwxMjgsMTQ0LDFdLCBcInNsYXRlZ3JleVwiOiBbMTEyLDEyOCwxNDQsMV0sXG4gIFwic25vd1wiOiBbMjU1LDI1MCwyNTAsMV0sIFwic3ByaW5nZ3JlZW5cIjogWzAsMjU1LDEyNywxXSxcbiAgXCJzdGVlbGJsdWVcIjogWzcwLDEzMCwxODAsMV0sIFwidGFuXCI6IFsyMTAsMTgwLDE0MCwxXSxcbiAgXCJ0ZWFsXCI6IFswLDEyOCwxMjgsMV0sIFwidGhpc3RsZVwiOiBbMjE2LDE5MSwyMTYsMV0sXG4gIFwidG9tYXRvXCI6IFsyNTUsOTksNzEsMV0sIFwidHVycXVvaXNlXCI6IFs2NCwyMjQsMjA4LDFdLFxuICBcInZpb2xldFwiOiBbMjM4LDEzMCwyMzgsMV0sIFwid2hlYXRcIjogWzI0NSwyMjIsMTc5LDFdLFxuICBcIndoaXRlXCI6IFsyNTUsMjU1LDI1NSwxXSwgXCJ3aGl0ZXNtb2tlXCI6IFsyNDUsMjQ1LDI0NSwxXSxcbiAgXCJ5ZWxsb3dcIjogWzI1NSwyNTUsMCwxXSwgXCJ5ZWxsb3dncmVlblwiOiBbMTU0LDIwNSw1MCwxXX1cblxuZnVuY3Rpb24gY2xhbXBfY3NzX2J5dGUoaSkgeyAgLy8gQ2xhbXAgdG8gaW50ZWdlciAwIC4uIDI1NS5cbiAgaSA9IE1hdGgucm91bmQoaSk7ICAvLyBTZWVtcyB0byBiZSB3aGF0IENocm9tZSBkb2VzICh2cyB0cnVuY2F0aW9uKS5cbiAgcmV0dXJuIGkgPCAwID8gMCA6IGkgPiAyNTUgPyAyNTUgOiBpO1xufVxuXG5mdW5jdGlvbiBjbGFtcF9jc3NfZmxvYXQoZikgeyAgLy8gQ2xhbXAgdG8gZmxvYXQgMC4wIC4uIDEuMC5cbiAgcmV0dXJuIGYgPCAwID8gMCA6IGYgPiAxID8gMSA6IGY7XG59XG5cbmZ1bmN0aW9uIHBhcnNlX2Nzc19pbnQoc3RyKSB7ICAvLyBpbnQgb3IgcGVyY2VudGFnZS5cbiAgaWYgKHN0cltzdHIubGVuZ3RoIC0gMV0gPT09ICclJylcbiAgICByZXR1cm4gY2xhbXBfY3NzX2J5dGUocGFyc2VGbG9hdChzdHIpIC8gMTAwICogMjU1KTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19ieXRlKHBhcnNlSW50KHN0cikpO1xufVxuXG5mdW5jdGlvbiBwYXJzZV9jc3NfZmxvYXQoc3RyKSB7ICAvLyBmbG9hdCBvciBwZXJjZW50YWdlLlxuICBpZiAoc3RyW3N0ci5sZW5ndGggLSAxXSA9PT0gJyUnKVxuICAgIHJldHVybiBjbGFtcF9jc3NfZmxvYXQocGFyc2VGbG9hdChzdHIpIC8gMTAwKTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19mbG9hdChwYXJzZUZsb2F0KHN0cikpO1xufVxuXG5mdW5jdGlvbiBjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgpIHtcbiAgaWYgKGggPCAwKSBoICs9IDE7XG4gIGVsc2UgaWYgKGggPiAxKSBoIC09IDE7XG5cbiAgaWYgKGggKiA2IDwgMSkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogaCAqIDY7XG4gIGlmIChoICogMiA8IDEpIHJldHVybiBtMjtcbiAgaWYgKGggKiAzIDwgMikgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDIvMyAtIGgpICogNjtcbiAgcmV0dXJuIG0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNTU0NvbG9yKGNzc19zdHIpIHtcbiAgLy8gUmVtb3ZlIGFsbCB3aGl0ZXNwYWNlLCBub3QgY29tcGxpYW50LCBidXQgc2hvdWxkIGp1c3QgYmUgbW9yZSBhY2NlcHRpbmcuXG4gIHZhciBzdHIgPSBjc3Nfc3RyLnJlcGxhY2UoLyAvZywgJycpLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gQ29sb3Iga2V5d29yZHMgKGFuZCB0cmFuc3BhcmVudCkgbG9va3VwLlxuICBpZiAoc3RyIGluIGtDU1NDb2xvclRhYmxlKSByZXR1cm4ga0NTU0NvbG9yVGFibGVbc3RyXS5zbGljZSgpOyAgLy8gZHVwLlxuXG4gIC8vICNhYmMgYW5kICNhYmMxMjMgc3ludGF4LlxuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gNCkge1xuICAgICAgdmFyIGl2ID0gcGFyc2VJbnQoc3RyLnN1YnN0cigxKSwgMTYpOyAgLy8gVE9ETyhkZWFubSk6IFN0cmljdGVyIHBhcnNpbmcuXG4gICAgICBpZiAoIShpdiA+PSAwICYmIGl2IDw9IDB4ZmZmKSkgcmV0dXJuIG51bGw7ICAvLyBDb3ZlcnMgTmFOLlxuICAgICAgcmV0dXJuIFsoKGl2ICYgMHhmMDApID4+IDQpIHwgKChpdiAmIDB4ZjAwKSA+PiA4KSxcbiAgICAgICAgICAgICAgKGl2ICYgMHhmMCkgfCAoKGl2ICYgMHhmMCkgPj4gNCksXG4gICAgICAgICAgICAgIChpdiAmIDB4ZikgfCAoKGl2ICYgMHhmKSA8PCA0KSxcbiAgICAgICAgICAgICAgMV07XG4gICAgfSBlbHNlIGlmIChzdHIubGVuZ3RoID09PSA3KSB7XG4gICAgICB2YXIgaXYgPSBwYXJzZUludChzdHIuc3Vic3RyKDEpLCAxNik7ICAvLyBUT0RPKGRlYW5tKTogU3RyaWN0ZXIgcGFyc2luZy5cbiAgICAgIGlmICghKGl2ID49IDAgJiYgaXYgPD0gMHhmZmZmZmYpKSByZXR1cm4gbnVsbDsgIC8vIENvdmVycyBOYU4uXG4gICAgICByZXR1cm4gWyhpdiAmIDB4ZmYwMDAwKSA+PiAxNixcbiAgICAgICAgICAgICAgKGl2ICYgMHhmZjAwKSA+PiA4LFxuICAgICAgICAgICAgICBpdiAmIDB4ZmYsXG4gICAgICAgICAgICAgIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIG9wID0gc3RyLmluZGV4T2YoJygnKSwgZXAgPSBzdHIuaW5kZXhPZignKScpO1xuICBpZiAob3AgIT09IC0xICYmIGVwICsgMSA9PT0gc3RyLmxlbmd0aCkge1xuICAgIHZhciBmbmFtZSA9IHN0ci5zdWJzdHIoMCwgb3ApO1xuICAgIHZhciBwYXJhbXMgPSBzdHIuc3Vic3RyKG9wKzEsIGVwLShvcCsxKSkuc3BsaXQoJywnKTtcbiAgICB2YXIgYWxwaGEgPSAxOyAgLy8gVG8gYWxsb3cgY2FzZSBmYWxsdGhyb3VnaC5cbiAgICBzd2l0Y2ggKGZuYW1lKSB7XG4gICAgICBjYXNlICdyZ2JhJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDQpIHJldHVybiBudWxsO1xuICAgICAgICBhbHBoYSA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXMucG9wKCkpO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2guXG4gICAgICBjYXNlICdyZ2InOlxuICAgICAgICBpZiAocGFyYW1zLmxlbmd0aCAhPT0gMykgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBbcGFyc2VfY3NzX2ludChwYXJhbXNbMF0pLFxuICAgICAgICAgICAgICAgIHBhcnNlX2Nzc19pbnQocGFyYW1zWzFdKSxcbiAgICAgICAgICAgICAgICBwYXJzZV9jc3NfaW50KHBhcmFtc1syXSksXG4gICAgICAgICAgICAgICAgYWxwaGFdO1xuICAgICAgY2FzZSAnaHNsYSc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSA0KSByZXR1cm4gbnVsbDtcbiAgICAgICAgYWxwaGEgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zLnBvcCgpKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoLlxuICAgICAgY2FzZSAnaHNsJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgaCA9ICgoKHBhcnNlRmxvYXQocGFyYW1zWzBdKSAlIDM2MCkgKyAzNjApICUgMzYwKSAvIDM2MDsgIC8vIDAgLi4gMVxuICAgICAgICAvLyBOT1RFKGRlYW5tKTogQWNjb3JkaW5nIHRvIHRoZSBDU1Mgc3BlYyBzL2wgc2hvdWxkIG9ubHkgYmVcbiAgICAgICAgLy8gcGVyY2VudGFnZXMsIGJ1dCB3ZSBkb24ndCBib3RoZXIgYW5kIGxldCBmbG9hdCBvciBwZXJjZW50YWdlLlxuICAgICAgICB2YXIgcyA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMV0pO1xuICAgICAgICB2YXIgbCA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMl0pO1xuICAgICAgICB2YXIgbTIgPSBsIDw9IDAuNSA/IGwgKiAocyArIDEpIDogbCArIHMgLSBsICogcztcbiAgICAgICAgdmFyIG0xID0gbCAqIDIgLSBtMjtcbiAgICAgICAgcmV0dXJuIFtjbGFtcF9jc3NfYnl0ZShjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgrMS8zKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoLTEvMykgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGFscGhhXTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG50cnkgeyBleHBvcnRzLnBhcnNlQ1NTQ29sb3IgPSBwYXJzZUNTU0NvbG9yIH0gY2F0Y2goZSkgeyB9XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZVR5cGVzID0gWydVbmtub3duJywgJ1BvaW50JywgJ0xpbmVTdHJpbmcnLCAnUG9seWdvbiddO1xuXG5mdW5jdGlvbiBpbmZpeChvcGVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiAndCcgKyBvcGVyYXRvciArIFZlY3RvclRpbGVGZWF0dXJlVHlwZXMuaW5kZXhPZih2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXScgKyBvcGVyYXRvciArIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdEluZml4KG9wZXJhdG9yKSB7XG4gICAgdmFyIG5vbnN0cmljdEluZml4ID0gaW5maXgob3BlcmF0b3IpO1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiBub25zdHJpY3RJbmZpeChfLCBrZXksIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAndHlwZW9mKHBbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSkgPT09IHR5cGVvZignICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpICsgJykgJiYgJyArXG4gICAgICAgICAgICAgICAgbm9uc3RyaWN0SW5maXgoXywga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgb3BlcmF0b3JzID0ge1xuICAgICc9PSc6IGluZml4KCc9PT0nKSxcbiAgICAnIT0nOiBpbmZpeCgnIT09JyksXG4gICAgJz4nOiBzdHJpY3RJbmZpeCgnPicpLFxuICAgICc8Jzogc3RyaWN0SW5maXgoJzwnKSxcbiAgICAnPD0nOiBzdHJpY3RJbmZpeCgnPD0nKSxcbiAgICAnPj0nOiBzdHJpY3RJbmZpeCgnPj0nKSxcbiAgICAnaW4nOiBmdW5jdGlvbihfLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMikubWFwKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gJygnICsgb3BlcmF0b3JzWyc9PSddKF8sIGtleSwgdmFsdWUpICsgJyknO1xuICAgICAgICB9KS5qb2luKCd8fCcpIHx8ICdmYWxzZSc7XG4gICAgfSxcbiAgICAnIWluJzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAnISgnICsgb3BlcmF0b3JzLmluLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKyAnKSc7XG4gICAgfSxcbiAgICAnYW55JzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLm1hcChmdW5jdGlvbihmaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBjb21waWxlKGZpbHRlcikgKyAnKSc7XG4gICAgICAgIH0pLmpvaW4oJ3x8JykgfHwgJ2ZhbHNlJztcbiAgICB9LFxuICAgICdhbGwnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkubWFwKGZ1bmN0aW9uKGZpbHRlcikge1xuICAgICAgICAgICAgcmV0dXJuICcoJyArIGNvbXBpbGUoZmlsdGVyKSArICcpJztcbiAgICAgICAgfSkuam9pbignJiYnKSB8fCAndHJ1ZSc7XG4gICAgfSxcbiAgICAnbm9uZSc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gJyEoJyArIG9wZXJhdG9ycy5hbnkuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICcpJztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb21waWxlKGZpbHRlcikge1xuICAgIHJldHVybiBvcGVyYXRvcnNbZmlsdGVyWzBdXS5hcHBseShmaWx0ZXIsIGZpbHRlcik7XG59XG5cbmZ1bmN0aW9uIHRydXRoKCkge1xuICAgIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgZmlsdGVyIGV4cHJlc3NlZCBhcyBuZXN0ZWQgYXJyYXlzLCByZXR1cm4gYSBuZXcgZnVuY3Rpb25cbiAqIHRoYXQgZXZhbHVhdGVzIHdoZXRoZXIgYSBnaXZlbiBmZWF0dXJlICh3aXRoIGEgLnByb3BlcnRpZXMgb3IgLnRhZ3MgcHJvcGVydHkpXG4gKiBwYXNzZXMgaXRzIHRlc3QuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gZmlsdGVyIG1hcGJveCBnbCBmaWx0ZXJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZmlsdGVyLWV2YWx1YXRpbmcgZnVuY3Rpb25cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgaWYgKCFmaWx0ZXIpIHJldHVybiB0cnV0aDtcbiAgICB2YXIgZmlsdGVyU3RyID0gJ3ZhciBwID0gZi5wcm9wZXJ0aWVzIHx8IGYudGFncyB8fCB7fSwgdCA9IGYudHlwZTsgcmV0dXJuICcgKyBjb21waWxlKGZpbHRlcikgKyAnOyc7XG4gICAgLy8ganNoaW50IGV2aWw6IHRydWVcbiAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCdmJywgZmlsdGVyU3RyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY2xpcDtcblxuLyogY2xpcCBmZWF0dXJlcyBiZXR3ZWVuIHR3byBheGlzLXBhcmFsbGVsIGxpbmVzOlxuICogICAgIHwgICAgICAgIHxcbiAqICBfX198X19fICAgICB8ICAgICAvXG4gKiAvICAgfCAgIFxcX19fX3xfX19fL1xuICogICAgIHwgICAgICAgIHxcbiAqL1xuXG5mdW5jdGlvbiBjbGlwKGZlYXR1cmVzLCBzY2FsZSwgazEsIGsyLCBheGlzLCBpbnRlcnNlY3QpIHtcblxuICAgIGsxIC89IHNjYWxlO1xuICAgIGsyIC89IHNjYWxlO1xuXG4gICAgdmFyIGNsaXBwZWQgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldLFxuICAgICAgICAgICAgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICAgICAgdHlwZSA9IGZlYXR1cmUudHlwZSxcbiAgICAgICAgICAgIG1pbiwgbWF4O1xuXG4gICAgICAgIGlmIChmZWF0dXJlLm1pbikge1xuICAgICAgICAgICAgbWluID0gZmVhdHVyZS5taW5bYXhpc107XG4gICAgICAgICAgICBtYXggPSBmZWF0dXJlLm1heFtheGlzXTtcblxuICAgICAgICAgICAgaWYgKG1pbiA+PSBrMSAmJiBtYXggPD0gazIpIHsgLy8gdHJpdmlhbCBhY2NlcHRcbiAgICAgICAgICAgICAgICBjbGlwcGVkLnB1c2goZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IGsyIHx8IG1heCA8IGsxKSBjb250aW51ZTsgLy8gdHJpdmlhbCByZWplY3RcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzbGljZXMgPSB0eXBlID09PSAxID9cbiAgICAgICAgICAgICAgICBjbGlwUG9pbnRzKGdlb21ldHJ5LCBrMSwgazIsIGF4aXMpIDpcbiAgICAgICAgICAgICAgICBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCB0eXBlID09PSAzKTtcblxuICAgICAgICBpZiAoc2xpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gaWYgYSBmZWF0dXJlIGdvdCBjbGlwcGVkLCBpdCB3aWxsIGxpa2VseSBnZXQgY2xpcHBlZCBvbiB0aGUgbmV4dCB6b29tIGxldmVsIGFzIHdlbGwsXG4gICAgICAgICAgICAvLyBzbyB0aGVyZSdzIG5vIG5lZWQgdG8gcmVjYWxjdWxhdGUgYmJveGVzXG4gICAgICAgICAgICBjbGlwcGVkLnB1c2goe1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5OiBzbGljZXMsXG4gICAgICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgICAgICB0YWdzOiBmZWF0dXJlc1tpXS50YWdzIHx8IG51bGxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWQubGVuZ3RoID8gY2xpcHBlZCA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGNsaXBQb2ludHMoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcykge1xuICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBnZW9tZXRyeS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYSA9IGdlb21ldHJ5W2ldLFxuICAgICAgICAgICAgYWsgPSBhW2F4aXNdO1xuXG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcbiAgICB9XG4gICAgcmV0dXJuIHNsaWNlO1xufVxuXG5mdW5jdGlvbiBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCBjbG9zZWQpIHtcblxuICAgIHZhciBzbGljZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgYWsgPSAwLFxuICAgICAgICAgICAgYmsgPSAwLFxuICAgICAgICAgICAgYiA9IG51bGwsXG4gICAgICAgICAgICBwb2ludHMgPSBnZW9tZXRyeVtpXSxcbiAgICAgICAgICAgIGFyZWEgPSBwb2ludHMuYXJlYSxcbiAgICAgICAgICAgIGRpc3QgPSBwb2ludHMuZGlzdCxcbiAgICAgICAgICAgIGxlbiA9IHBvaW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhLCBqO1xuXG4gICAgICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW4gLSAxOyBqKyspIHtcbiAgICAgICAgICAgIGEgPSBiIHx8IHBvaW50c1tqXTtcbiAgICAgICAgICAgIGIgPSBwb2ludHNbaiArIDFdO1xuICAgICAgICAgICAgYWsgPSBiayB8fCBhW2F4aXNdO1xuICAgICAgICAgICAgYmsgPSBiW2F4aXNdO1xuXG4gICAgICAgICAgICBpZiAoYWsgPCBrMSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKChiayA+IGsyKSkgeyAvLyAtLS18LS0tLS18LS0+XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSwgaW50ZXJzZWN0KGEsIGIsIGsyKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+PSBrMSkgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazEpKTsgLy8gLS0tfC0tPiAgfFxuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFrID4gazIpIHtcblxuICAgICAgICAgICAgICAgIGlmICgoYmsgPCBrMSkpIHsgLy8gPC0tfC0tLS0tfC0tLVxuICAgICAgICAgICAgICAgICAgICBzbGljZS5wdXNoKGludGVyc2VjdChhLCBiLCBrMiksIGludGVyc2VjdChhLCBiLCBrMSkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb3NlZCkgc2xpY2UgPSBuZXdTbGljZShzbGljZXMsIHNsaWNlLCBhcmVhLCBkaXN0KTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmsgPD0gazIpIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsyKSk7IC8vIHwgIDwtLXwtLS1cblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goYSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYmsgPCBrMSkgeyAvLyA8LS18LS0tICB8XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+IGsyKSB7IC8vIHwgIC0tLXwtLT5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjbG9zZWQpIHNsaWNlID0gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHwgLS0+IHxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkZCB0aGUgbGFzdCBwb2ludFxuICAgICAgICBhID0gcG9pbnRzW2xlbiAtIDFdO1xuICAgICAgICBhayA9IGFbYXhpc107XG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcblxuICAgICAgICAvLyBjbG9zZSB0aGUgcG9seWdvbiBpZiBpdHMgZW5kcG9pbnRzIGFyZSBub3QgdGhlIHNhbWUgYWZ0ZXIgY2xpcHBpbmdcbiAgICAgICAgaWYgKGNsb3NlZCAmJiBzbGljZVswXSAhPT0gc2xpY2Vbc2xpY2UubGVuZ3RoIC0gMV0pIHNsaWNlLnB1c2goc2xpY2VbMF0pO1xuXG4gICAgICAgIC8vIGFkZCB0aGUgZmluYWwgc2xpY2VcbiAgICAgICAgbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWNlcztcbn1cblxuZnVuY3Rpb24gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCkge1xuICAgIGlmIChzbGljZS5sZW5ndGgpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3QgcmVjYWxjdWxhdGUgdGhlIGFyZWEvbGVuZ3RoIG9mIHRoZSB1bmNsaXBwZWQgZ2VvbWV0cnkgYmVjYXVzZSB0aGUgY2FzZSB3aGVyZSBpdCBnb2VzXG4gICAgICAgIC8vIGJlbG93IHRoZSB2aXNpYmlsaXR5IHRocmVzaG9sZCBhcyBhIHJlc3VsdCBvZiBjbGlwcGluZyBpcyByYXJlLCBzbyB3ZSBhdm9pZCBkb2luZyB1bm5lY2Vzc2FyeSB3b3JrXG4gICAgICAgIHNsaWNlLmFyZWEgPSBhcmVhO1xuICAgICAgICBzbGljZS5kaXN0ID0gZGlzdDtcblxuICAgICAgICBzbGljZXMucHVzaChzbGljZSk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXJ0O1xuXG52YXIgc2ltcGxpZnkgPSByZXF1aXJlKCcuL3NpbXBsaWZ5Jyk7XG5cbi8vIGNvbnZlcnRzIEdlb0pTT04gZmVhdHVyZSBpbnRvIGFuIGludGVybWVkaWF0ZSBwcm9qZWN0ZWQgSlNPTiB2ZWN0b3IgZm9ybWF0IHdpdGggc2ltcGxpZmljYXRpb24gZGF0YVxuXG5mdW5jdGlvbiBjb252ZXJ0KGRhdGEsIHRvbGVyYW5jZSkge1xuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEuZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnZlcnRGZWF0dXJlKGZlYXR1cmVzLCBkYXRhLmZlYXR1cmVzW2ldLCB0b2xlcmFuY2UpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdGZWF0dXJlJykge1xuICAgICAgICBjb252ZXJ0RmVhdHVyZShmZWF0dXJlcywgZGF0YSwgdG9sZXJhbmNlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNpbmdsZSBnZW9tZXRyeSBvciBhIGdlb21ldHJ5IGNvbGxlY3Rpb25cbiAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtnZW9tZXRyeTogZGF0YX0sIHRvbGVyYW5jZSk7XG4gICAgfVxuICAgIHJldHVybiBmZWF0dXJlcztcbn1cblxuZnVuY3Rpb24gY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIGZlYXR1cmUsIHRvbGVyYW5jZSkge1xuICAgIHZhciBnZW9tID0gZmVhdHVyZS5nZW9tZXRyeSxcbiAgICAgICAgdHlwZSA9IGdlb20udHlwZSxcbiAgICAgICAgY29vcmRzID0gZ2VvbS5jb29yZGluYXRlcyxcbiAgICAgICAgdGFncyA9IGZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgaSwgaiwgcmluZ3M7XG5cbiAgICBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBbcHJvamVjdFBvaW50KGNvb3JkcyldKSk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdNdWx0aVBvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBwcm9qZWN0KGNvb3JkcykpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0xpbmVTdHJpbmcnKSB7XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIDIsIFtwcm9qZWN0KGNvb3JkcywgdG9sZXJhbmNlKV0pKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ011bHRpTGluZVN0cmluZycgfHwgdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIHJpbmdzID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmdzLnB1c2gocHJvamVjdChjb29yZHNbaV0sIHRvbGVyYW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIHR5cGUgPT09ICdQb2x5Z29uJyA/IDMgOiAyLCByaW5ncykpO1xuXG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICByaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29vcmRzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChwcm9qZWN0KGNvb3Jkc1tpXVtqXSwgdG9sZXJhbmNlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmVhdHVyZXMucHVzaChjcmVhdGUodGFncywgMywgcmluZ3MpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20uZ2VvbWV0cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeTogZ2VvbS5nZW9tZXRyaWVzW2ldLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHRhZ3NcbiAgICAgICAgICAgIH0sIHRvbGVyYW5jZSk7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVW5zdXBwb3J0ZWQgR2VvSlNPTiB0eXBlOiAnICsgZ2VvbS50eXBlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZSh0YWdzLCB0eXBlLCBnZW9tZXRyeSkge1xuICAgIHZhciBmZWF0dXJlID0ge1xuICAgICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIHRhZ3M6IHRhZ3MgfHwgbnVsbCxcbiAgICAgICAgbWluOiBbMSwgMV0sIC8vIGluaXRpYWwgYmJveCB2YWx1ZXM7XG4gICAgICAgIG1heDogWzAsIDBdICAvLyBub3RlIHRoYXQgYWxsIGNvb3JkcyBhcmUgaW4gWzAuLjFdIHJhbmdlXG4gICAgfTtcbiAgICBjYWxjQkJveChmZWF0dXJlKTtcbiAgICByZXR1cm4gZmVhdHVyZTtcbn1cblxuZnVuY3Rpb24gcHJvamVjdChsb25sYXRzLCB0b2xlcmFuY2UpIHtcbiAgICB2YXIgcHJvamVjdGVkID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb25sYXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByb2plY3RlZC5wdXNoKHByb2plY3RQb2ludChsb25sYXRzW2ldKSk7XG4gICAgfVxuICAgIGlmICh0b2xlcmFuY2UpIHtcbiAgICAgICAgc2ltcGxpZnkocHJvamVjdGVkLCB0b2xlcmFuY2UpO1xuICAgICAgICBjYWxjU2l6ZShwcm9qZWN0ZWQpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvamVjdGVkO1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0UG9pbnQocCkge1xuICAgIHZhciBzaW4gPSBNYXRoLnNpbihwWzFdICogTWF0aC5QSSAvIDE4MCksXG4gICAgICAgIHggPSAocFswXSAvIDM2MCArIDAuNSksXG4gICAgICAgIHkgPSAoMC41IC0gMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyBNYXRoLlBJKTtcbiAgICByZXR1cm4gW3gsIHksIDBdO1xufVxuXG4vLyBjYWxjdWxhdGUgYXJlYSBhbmQgbGVuZ3RoIG9mIHRoZSBwb2x5XG5mdW5jdGlvbiBjYWxjU2l6ZShwb2ludHMpIHtcbiAgICB2YXIgYXJlYSA9IDAsXG4gICAgICAgIGRpc3QgPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGEsIGI7IGkgPCBwb2ludHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGEgPSBiIHx8IHBvaW50c1tpXTtcbiAgICAgICAgYiA9IHBvaW50c1tpICsgMV07XG5cbiAgICAgICAgYXJlYSArPSBhWzBdICogYlsxXSAtIGJbMF0gKiBhWzFdO1xuXG4gICAgICAgIC8vIHVzZSBNYW5oYXR0YW4gZGlzdGFuY2UgaW5zdGVhZCBvZiBFdWNsaWRpYW4gb25lIHRvIGF2b2lkIGV4cGVuc2l2ZSBzcXVhcmUgcm9vdCBjb21wdXRhdGlvblxuICAgICAgICBkaXN0ICs9IE1hdGguYWJzKGJbMF0gLSBhWzBdKSArIE1hdGguYWJzKGJbMV0gLSBhWzFdKTtcbiAgICB9XG4gICAgcG9pbnRzLmFyZWEgPSBNYXRoLmFicyhhcmVhIC8gMik7XG4gICAgcG9pbnRzLmRpc3QgPSBkaXN0O1xufVxuXG4vLyBjYWxjdWxhdGUgdGhlIGZlYXR1cmUgYm91bmRpbmcgYm94IGZvciBmYXN0ZXIgY2xpcHBpbmcgbGF0ZXJcbmZ1bmN0aW9uIGNhbGNCQm94KGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICBtaW4gPSBmZWF0dXJlLm1pbixcbiAgICAgICAgbWF4ID0gZmVhdHVyZS5tYXg7XG5cbiAgICBpZiAoZmVhdHVyZS50eXBlID09PSAxKSBjYWxjUmluZ0JCb3gobWluLCBtYXgsIGdlb21ldHJ5KTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIGNhbGNSaW5nQkJveChtaW4sIG1heCwgZ2VvbWV0cnlbaV0pO1xuXG4gICAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGNhbGNSaW5nQkJveChtaW4sIG1heCwgcG9pbnRzKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcCA9IHBvaW50c1tpXTtcbiAgICAgICAgbWluWzBdID0gTWF0aC5taW4ocFswXSwgbWluWzBdKTtcbiAgICAgICAgbWF4WzBdID0gTWF0aC5tYXgocFswXSwgbWF4WzBdKTtcbiAgICAgICAgbWluWzFdID0gTWF0aC5taW4ocFsxXSwgbWluWzFdKTtcbiAgICAgICAgbWF4WzFdID0gTWF0aC5tYXgocFsxXSwgbWF4WzFdKTtcbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZ2VvanNvbnZ0O1xuXG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4vY29udmVydCcpLCAvLyBHZW9KU09OIGNvbnZlcnNpb24gYW5kIHByZXByb2Nlc3NpbmdcbiAgICBjbGlwID0gcmVxdWlyZSgnLi9jbGlwJyksICAgICAgIC8vIHN0cmlwZSBjbGlwcGluZyBhbGdvcml0aG1cbiAgICBjcmVhdGVUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7IC8vIGZpbmFsIHNpbXBsaWZpZWQgdGlsZSBnZW5lcmF0aW9uXG5cblxuZnVuY3Rpb24gZ2VvanNvbnZ0KGRhdGEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IEdlb0pTT05WVChkYXRhLCBvcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gR2VvSlNPTlZUKGRhdGEsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zID0gZXh0ZW5kKE9iamVjdC5jcmVhdGUodGhpcy5vcHRpb25zKSwgb3B0aW9ucyk7XG5cbiAgICB2YXIgZGVidWcgPSBvcHRpb25zLmRlYnVnO1xuXG4gICAgaWYgKGRlYnVnKSBjb25zb2xlLnRpbWUoJ3ByZXByb2Nlc3MgZGF0YScpO1xuXG4gICAgdmFyIHoyID0gMSA8PCBvcHRpb25zLmJhc2Vab29tLCAvLyAyXnpcbiAgICAgICAgZmVhdHVyZXMgPSBjb252ZXJ0KGRhdGEsIG9wdGlvbnMudG9sZXJhbmNlIC8gKHoyICogb3B0aW9ucy5leHRlbnQpKTtcblxuICAgIHRoaXMudGlsZXMgPSB7fTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoJ3ByZXByb2Nlc3MgZGF0YScpO1xuICAgICAgICBjb25zb2xlLnRpbWUoJ2dlbmVyYXRlIHRpbGVzIHVwIHRvIHonICsgb3B0aW9ucy5tYXhab29tKTtcbiAgICAgICAgdGhpcy5zdGF0cyA9IHt9O1xuICAgICAgICB0aGlzLnRvdGFsID0gMDtcbiAgICB9XG5cbiAgICAvLyBzdGFydCBzbGljaW5nIGZyb20gdGhlIHRvcCB0aWxlIGRvd25cbiAgICB0aGlzLnNwbGl0VGlsZShmZWF0dXJlcywgMCwgMCwgMCk7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2ZlYXR1cmVzOiAlZCwgcG9pbnRzOiAlZCcsIHRoaXMudGlsZXNbMF0ubnVtRmVhdHVyZXMsIHRoaXMudGlsZXNbMF0ubnVtUG9pbnRzKTtcbiAgICAgICAgY29uc29sZS50aW1lRW5kKCdnZW5lcmF0ZSB0aWxlcyB1cCB0byB6JyArIG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCd0aWxlcyBnZW5lcmF0ZWQ6JywgdGhpcy50b3RhbCwgSlNPTi5zdHJpbmdpZnkodGhpcy5zdGF0cykpO1xuICAgIH1cbn1cblxuR2VvSlNPTlZULnByb3RvdHlwZS5vcHRpb25zID0ge1xuICAgIGJhc2Vab29tOiAxNCwgICAvLyBtYXggem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgb25cbiAgICBtYXhab29tOiA0LCAgICAgLy8gem9vbSB0byBzbGljZSBkb3duIHRvIG9uIGZpcnN0IHBhc3NcbiAgICBtYXhQb2ludHM6IDEwMCwgLy8gc3RvcCBzbGljaW5nIGEgdGlsZSBiZWxvdyB0aGlzIG51bWJlciBvZiBwb2ludHNcbiAgICB0b2xlcmFuY2U6IDMsICAgLy8gc2ltcGxpZmljYXRpb24gdG9sZXJhbmNlIChoaWdoZXIgbWVhbnMgc2ltcGxlcilcbiAgICBleHRlbnQ6IDQwOTYsICAgLy8gdGlsZSBleHRlbnRcbiAgICBidWZmZXI6IDY0LCAgICAgLy8gdGlsZSBidWZmZXIgb24gZWFjaCBzaWRlXG4gICAgZGVidWc6IDAgICAgICAgIC8vIGxvZ2dpbmcgbGV2ZWwgKDAsIDEgb3IgMilcbn07XG5cbkdlb0pTT05WVC5wcm90b3R5cGUuc3BsaXRUaWxlID0gZnVuY3Rpb24gKGZlYXR1cmVzLCB6LCB4LCB5LCBjeiwgY3gsIGN5KSB7XG5cbiAgICB2YXIgc3RhY2sgPSBbZmVhdHVyZXMsIHosIHgsIHldLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICBkZWJ1ZyA9IG9wdGlvbnMuZGVidWcsXG4gICAgICAgIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50LFxuICAgICAgICBidWZmZXIgPSBvcHRpb25zLmJ1ZmZlcjtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHByb2Nlc3NpbmcgcXVldWVcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoKSB7XG4gICAgICAgIGZlYXR1cmVzID0gc3RhY2suc2hpZnQoKTtcbiAgICAgICAgeiA9IHN0YWNrLnNoaWZ0KCk7XG4gICAgICAgIHggPSBzdGFjay5zaGlmdCgpO1xuICAgICAgICB5ID0gc3RhY2suc2hpZnQoKTtcblxuICAgICAgICB2YXIgejIgPSAxIDw8IHosXG4gICAgICAgICAgICBpZCA9IHRvSUQoeiwgeCwgeSksXG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF0sXG4gICAgICAgICAgICB0aWxlVG9sZXJhbmNlID0geiA9PT0gb3B0aW9ucy5iYXNlWm9vbSA/IDAgOiBvcHRpb25zLnRvbGVyYW5jZSAvICh6MiAqIGV4dGVudCk7XG5cbiAgICAgICAgaWYgKCF0aWxlKSB7XG4gICAgICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NyZWF0aW9uJyk7XG5cbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLnRpbGVzW2lkXSA9IGNyZWF0ZVRpbGUoZmVhdHVyZXMsIHoyLCB4LCB5LCB0aWxlVG9sZXJhbmNlLCBleHRlbnQsIHogPT09IG9wdGlvbnMuYmFzZVpvb20pO1xuXG4gICAgICAgICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVidWcgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCd0aWxlIHolZC0lZC0lZCAoZmVhdHVyZXM6ICVkLCBwb2ludHM6ICVkLCBzaW1wbGlmaWVkOiAlZCknLFxuICAgICAgICAgICAgICAgICAgICAgICAgeiwgeCwgeSwgdGlsZS5udW1GZWF0dXJlcywgdGlsZS5udW1Qb2ludHMsIHRpbGUubnVtU2ltcGxpZmllZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZCgnY3JlYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICd6JyArIHogKyAnOic7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0c1trZXldID0gKHRoaXMuc3RhdHNba2V5XSB8fCAwKSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy50b3RhbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjeiAmJiAoeiA9PT0gb3B0aW9ucy5tYXhab29tIHx8IHRpbGUubnVtUG9pbnRzIDw9IG9wdGlvbnMubWF4UG9pbnRzIHx8XG4gICAgICAgICAgICAgICAgaXNDbGlwcGVkU3F1YXJlKHRpbGUuZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSkgfHwgeiA9PT0gb3B0aW9ucy5iYXNlWm9vbSB8fCB6ID09PSBjeikge1xuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSBmZWF0dXJlcztcbiAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBzdG9wIHRpbGluZ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN6KSB0aWxlLnNvdXJjZSA9IGZlYXR1cmVzO1xuICAgICAgICBlbHNlIHRpbGUuc291cmNlID0gbnVsbDtcblxuICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NsaXBwaW5nJyk7XG5cbiAgICAgICAgLy8gdmFsdWVzIHdlJ2xsIHVzZSBmb3IgY2xpcHBpbmdcbiAgICAgICAgdmFyIGsxID0gMC41ICogYnVmZmVyIC8gZXh0ZW50LFxuICAgICAgICAgICAgazIgPSAwLjUgLSBrMSxcbiAgICAgICAgICAgIGszID0gMC41ICsgazEsXG4gICAgICAgICAgICBrNCA9IDEgKyBrMSxcblxuICAgICAgICAgICAgdGwsIGJsLCB0ciwgYnIsIGxlZnQsIHJpZ2h0LFxuICAgICAgICAgICAgbSwgZ29MZWZ0LCBnb1RvcDtcblxuICAgICAgICBpZiAoY3opIHsgLy8gaWYgd2UgaGF2ZSBhIHNwZWNpZmljIHRpbGUgdG8gZHJpbGwgZG93biB0bywgY2FsY3VsYXRlIHdoZXJlIHRvIGdvXG4gICAgICAgICAgICBtID0gMSA8PCAoY3ogLSB6KTtcbiAgICAgICAgICAgIGdvTGVmdCA9IGN4IC8gbSAtIHggPCAwLjU7XG4gICAgICAgICAgICBnb1RvcCA9IGN5IC8gbSAtIHkgPCAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICB0bCA9IGJsID0gdHIgPSBiciA9IGxlZnQgPSByaWdodCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCFjeiB8fCAgZ29MZWZ0KSBsZWZ0ICA9IGNsaXAoZmVhdHVyZXMsIHoyLCB4IC0gazEsIHggKyBrMywgMCwgaW50ZXJzZWN0WCk7XG4gICAgICAgIGlmICghY3ogfHwgIWdvTGVmdCkgcmlnaHQgPSBjbGlwKGZlYXR1cmVzLCB6MiwgeCArIGsyLCB4ICsgazQsIDAsIGludGVyc2VjdFgpO1xuXG4gICAgICAgIGlmIChsZWZ0KSB7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICBnb1RvcCkgdGwgPSBjbGlwKGxlZnQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYmwgPSBjbGlwKGxlZnQsIHoyLCB5ICsgazIsIHkgKyBrNCwgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgIGlmICghY3ogfHwgIGdvVG9wKSB0ciA9IGNsaXAocmlnaHQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYnIgPSBjbGlwKHJpZ2h0LCB6MiwgeSArIGsyLCB5ICsgazQsIDEsIGludGVyc2VjdFkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS50aW1lRW5kKCdjbGlwcGluZycpO1xuXG4gICAgICAgIGlmICh0bCkgc3RhY2sucHVzaCh0bCwgeiArIDEsIHggKiAyLCAgICAgeSAqIDIpO1xuICAgICAgICBpZiAoYmwpIHN0YWNrLnB1c2goYmwsIHogKyAxLCB4ICogMiwgICAgIHkgKiAyICsgMSk7XG4gICAgICAgIGlmICh0cikgc3RhY2sucHVzaCh0ciwgeiArIDEsIHggKiAyICsgMSwgeSAqIDIpO1xuICAgICAgICBpZiAoYnIpIHN0YWNrLnB1c2goYnIsIHogKyAxLCB4ICogMiArIDEsIHkgKiAyICsgMSk7XG4gICAgfVxufTtcblxuR2VvSlNPTlZULnByb3RvdHlwZS5nZXRUaWxlID0gZnVuY3Rpb24gKHosIHgsIHkpIHtcbiAgICB2YXIgaWQgPSB0b0lEKHosIHgsIHkpO1xuICAgIGlmICh0aGlzLnRpbGVzW2lkXSkgcmV0dXJuIHRoaXMudGlsZXNbaWRdO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgIGRlYnVnID0gb3B0aW9ucy5kZWJ1ZztcblxuICAgIGlmIChkZWJ1ZyA+IDEpIGNvbnNvbGUubG9nKCdkcmlsbGluZyBkb3duIHRvIHolZC0lZC0lZCcsIHosIHgsIHkpO1xuXG4gICAgdmFyIHowID0geixcbiAgICAgICAgeDAgPSB4LFxuICAgICAgICB5MCA9IHksXG4gICAgICAgIHBhcmVudDtcblxuICAgIHdoaWxlICghcGFyZW50ICYmIHowID4gMCkge1xuICAgICAgICB6MC0tO1xuICAgICAgICB4MCA9IE1hdGguZmxvb3IoeDAgLyAyKTtcbiAgICAgICAgeTAgPSBNYXRoLmZsb29yKHkwIC8gMik7XG4gICAgICAgIHBhcmVudCA9IHRoaXMudGlsZXNbdG9JRCh6MCwgeDAsIHkwKV07XG4gICAgfVxuXG4gICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS5sb2coJ2ZvdW5kIHBhcmVudCB0aWxlIHolZC0lZC0lZCcsIHowLCB4MCwgeTApO1xuXG4gICAgLy8gaWYgd2UgZm91bmQgYSBwYXJlbnQgdGlsZSBjb250YWluaW5nIHRoZSBvcmlnaW5hbCBnZW9tZXRyeSwgd2UgY2FuIGRyaWxsIGRvd24gZnJvbSBpdFxuICAgIGlmIChwYXJlbnQuc291cmNlKSB7XG4gICAgICAgIGlmIChpc0NsaXBwZWRTcXVhcmUocGFyZW50LmZlYXR1cmVzLCBvcHRpb25zLmV4dGVudCwgb3B0aW9ucy5idWZmZXIpKSByZXR1cm4gcGFyZW50O1xuXG4gICAgICAgIGlmIChkZWJ1ZykgY29uc29sZS50aW1lKCdkcmlsbGluZyBkb3duJyk7XG4gICAgICAgIHRoaXMuc3BsaXRUaWxlKHBhcmVudC5zb3VyY2UsIHowLCB4MCwgeTAsIHosIHgsIHkpO1xuICAgICAgICBpZiAoZGVidWcpIGNvbnNvbGUudGltZUVuZCgnZHJpbGxpbmcgZG93bicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRpbGVzW2lkXTtcbn07XG5cbi8vIGNoZWNrcyB3aGV0aGVyIGEgdGlsZSBpcyBhIHdob2xlLWFyZWEgZmlsbCBhZnRlciBjbGlwcGluZzsgaWYgaXQgaXMsIHRoZXJlJ3Mgbm8gc2Vuc2Ugc2xpY2luZyBpdCBmdXJ0aGVyXG5mdW5jdGlvbiBpc0NsaXBwZWRTcXVhcmUoZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSB7XG4gICAgaWYgKGZlYXR1cmVzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1swXTtcbiAgICBpZiAoZmVhdHVyZS50eXBlICE9PSAzIHx8IGZlYXR1cmUuZ2VvbWV0cnkubGVuZ3RoID4gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlLmdlb21ldHJ5WzBdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwID0gZmVhdHVyZS5nZW9tZXRyeVswXVtpXTtcbiAgICAgICAgaWYgKChwWzBdICE9PSAtYnVmZmVyICYmIHBbMF0gIT09IGV4dGVudCArIGJ1ZmZlcikgfHxcbiAgICAgICAgICAgIChwWzFdICE9PSAtYnVmZmVyICYmIHBbMV0gIT09IGV4dGVudCArIGJ1ZmZlcikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHRvSUQoeiwgeCwgeSkge1xuICAgIHJldHVybiAoKCgxIDw8IHopICogeSArIHgpICogMzIpICsgejtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0WChhLCBiLCB4KSB7XG4gICAgcmV0dXJuIFt4LCAoeCAtIGFbMF0pICogKGJbMV0gLSBhWzFdKSAvIChiWzBdIC0gYVswXSkgKyBhWzFdLCAxXTtcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFkoYSwgYiwgeSkge1xuICAgIHJldHVybiBbKHkgLSBhWzFdKSAqIChiWzBdIC0gYVswXSkgLyAoYlsxXSAtIGFbMV0pICsgYVswXSwgeSwgMV07XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMpIHtcbiAgICBmb3IgKHZhciBpIGluIHNyYykgZGVzdFtpXSA9IHNyY1tpXTtcbiAgICByZXR1cm4gZGVzdDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBzaW1wbGlmeTtcblxuLy8gY2FsY3VsYXRlIHNpbXBsaWZpY2F0aW9uIGRhdGEgdXNpbmcgb3B0aW1pemVkIERvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1cblxuZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcblxuICAgIHZhciBzcVRvbGVyYW5jZSA9IHRvbGVyYW5jZSAqIHRvbGVyYW5jZSxcbiAgICAgICAgbGVuID0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgZmlyc3QgPSAwLFxuICAgICAgICBsYXN0ID0gbGVuIC0gMSxcbiAgICAgICAgc3RhY2sgPSBbXSxcbiAgICAgICAgaSwgbWF4U3FEaXN0LCBzcURpc3QsIGluZGV4O1xuXG4gICAgLy8gYWx3YXlzIHJldGFpbiB0aGUgZW5kcG9pbnRzICgxIGlzIHRoZSBtYXggdmFsdWUpXG4gICAgcG9pbnRzW2ZpcnN0XVsyXSA9IDE7XG4gICAgcG9pbnRzW2xhc3RdWzJdID0gMTtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHN0YWNrXG4gICAgd2hpbGUgKGxhc3QpIHtcblxuICAgICAgICBtYXhTcURpc3QgPSAwO1xuXG4gICAgICAgIGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgc3FEaXN0ID0gZ2V0U3FTZWdEaXN0KHBvaW50c1tpXSwgcG9pbnRzW2ZpcnN0XSwgcG9pbnRzW2xhc3RdKTtcblxuICAgICAgICAgICAgaWYgKHNxRGlzdCA+IG1heFNxRGlzdCkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBtYXhTcURpc3QgPSBzcURpc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4U3FEaXN0ID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHBvaW50c1tpbmRleF1bMl0gPSBtYXhTcURpc3Q7IC8vIHNhdmUgdGhlIHBvaW50IGltcG9ydGFuY2UgaW4gc3F1YXJlZCBwaXhlbHMgYXMgYSB6IGNvb3JkaW5hdGVcbiAgICAgICAgICAgIHN0YWNrLnB1c2goZmlyc3QsIGluZGV4LCBpbmRleCwgbGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXN0ID0gc3RhY2sucG9wKCk7XG4gICAgICAgIGZpcnN0ID0gc3RhY2sucG9wKCk7XG4gICAgfVxufVxuXG4vLyBzcXVhcmUgZGlzdGFuY2UgZnJvbSBhIHBvaW50IHRvIGEgc2VnbWVudFxuZnVuY3Rpb24gZ2V0U3FTZWdEaXN0KHAsIGEsIGIpIHtcblxuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sXG4gICAgICAgIGJ4ID0gYlswXSwgYnkgPSBiWzFdLFxuICAgICAgICBweCA9IHBbMF0sIHB5ID0gcFsxXSxcbiAgICAgICAgZHggPSBieCAtIHgsXG4gICAgICAgIGR5ID0gYnkgLSB5O1xuXG4gICAgaWYgKGR4ICE9PSAwIHx8IGR5ICE9PSAwKSB7XG5cbiAgICAgICAgdmFyIHQgPSAoKHB4IC0geCkgKiBkeCArIChweSAtIHkpICogZHkpIC8gKGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZiAodCA+IDEpIHtcbiAgICAgICAgICAgIHggPSBieDtcbiAgICAgICAgICAgIHkgPSBieTtcblxuICAgICAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICAgICAgICB4ICs9IGR4ICogdDtcbiAgICAgICAgICAgIHkgKz0gZHkgKiB0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHggPSBweCAtIHg7XG4gICAgZHkgPSBweSAtIHk7XG5cbiAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGlsZTtcblxuZnVuY3Rpb24gY3JlYXRlVGlsZShmZWF0dXJlcywgejIsIHR4LCB0eSwgdG9sZXJhbmNlLCBleHRlbnQsIG5vU2ltcGxpZnkpIHtcbiAgICB2YXIgdGlsZSA9IHtcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgICBudW1Qb2ludHM6IDAsXG4gICAgICAgIG51bVNpbXBsaWZpZWQ6IDAsXG4gICAgICAgIG51bUZlYXR1cmVzOiAwLFxuICAgICAgICBzb3VyY2U6IG51bGxcbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGlsZS5udW1GZWF0dXJlcysrO1xuICAgICAgICBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmVzW2ldLCB6MiwgdHgsIHR5LCB0b2xlcmFuY2UsIGV4dGVudCwgbm9TaW1wbGlmeSk7XG4gICAgfVxuICAgIHJldHVybiB0aWxlO1xufVxuXG5mdW5jdGlvbiBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmUsIHoyLCB0eCwgdHksIHRvbGVyYW5jZSwgZXh0ZW50LCBub1NpbXBsaWZ5KSB7XG5cbiAgICB2YXIgZ2VvbSA9IGZlYXR1cmUuZ2VvbWV0cnksXG4gICAgICAgIHR5cGUgPSBmZWF0dXJlLnR5cGUsXG4gICAgICAgIHRyYW5zZm9ybWVkID0gW10sXG4gICAgICAgIHNxVG9sZXJhbmNlID0gdG9sZXJhbmNlICogdG9sZXJhbmNlLFxuICAgICAgICBpLCBqLCByaW5nLCBwO1xuXG4gICAgaWYgKHR5cGUgPT09IDEpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWVkLnB1c2godHJhbnNmb3JtUG9pbnQoZ2VvbVtpXSwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgdGlsZS5udW1TaW1wbGlmaWVkKys7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gc2ltcGxpZnkgYW5kIHRyYW5zZm9ybSBwcm9qZWN0ZWQgY29vcmRpbmF0ZXMgZm9yIHRpbGUgZ2VvbWV0cnlcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmcgPSBnZW9tW2ldO1xuXG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHRpbnkgcG9seWxpbmVzICYgcG9seWdvbnNcbiAgICAgICAgICAgIGlmICghbm9TaW1wbGlmeSAmJiAoKHR5cGUgPT09IDIgJiYgcmluZy5kaXN0IDwgdG9sZXJhbmNlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodHlwZSA9PT0gMyAmJiByaW5nLmFyZWEgPCBzcVRvbGVyYW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgdGlsZS5udW1Qb2ludHMgKz0gcmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZFJpbmcgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcmluZ1tqXTtcbiAgICAgICAgICAgICAgICAvLyBrZWVwIHBvaW50cyB3aXRoIGltcG9ydGFuY2UgPiB0b2xlcmFuY2VcbiAgICAgICAgICAgICAgICBpZiAobm9TaW1wbGlmeSB8fCBwWzJdID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRSaW5nLnB1c2godHJhbnNmb3JtUG9pbnQocCwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICAgICAgICAgIHRpbGUubnVtU2ltcGxpZmllZCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cmFuc2Zvcm1lZC5wdXNoKHRyYW5zZm9ybWVkUmluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNmb3JtZWQubGVuZ3RoKSB7XG4gICAgICAgIHRpbGUuZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICBnZW9tZXRyeTogdHJhbnNmb3JtZWQsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgdGFnczogZmVhdHVyZS50YWdzIHx8IG51bGxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludChwLCB6MiwgdHgsIHR5LCBleHRlbnQpIHtcbiAgICB2YXIgeCA9IE1hdGgucm91bmQoZXh0ZW50ICogKHBbMF0gKiB6MiAtIHR4KSksXG4gICAgICAgIHkgPSBNYXRoLnJvdW5kKGV4dGVudCAqIChwWzFdICogejIgLSB0eSkpO1xuICAgIHJldHVybiBbeCwgeV07XG59XG4iLCIvKipcbiAqIEBmaWxlb3ZlcnZpZXcgZ2wtbWF0cml4IC0gSGlnaCBwZXJmb3JtYW5jZSBtYXRyaXggYW5kIHZlY3RvciBvcGVyYXRpb25zXG4gKiBAYXV0aG9yIEJyYW5kb24gSm9uZXNcbiAqIEBhdXRob3IgQ29saW4gTWFjS2VuemllIElWXG4gKiBAdmVyc2lvbiAyLjIuMVxuICovXG5cbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbihmdW5jdGlvbihfZ2xvYmFsKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIHZhciBzaGltID0ge307XG4gIGlmICh0eXBlb2YoZXhwb3J0cykgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHt9O1xuICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gc2hpbS5leHBvcnRzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBhIGJyb3dzZXIsIGRlZmluZSBpdHMgbmFtZXNwYWNlcyBpbiBnbG9iYWxcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHR5cGVvZih3aW5kb3cpICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IF9nbG9iYWw7XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBjb21tb25qcywgZGVmaW5lIGl0cyBuYW1lc3BhY2VzIGluIGV4cG9ydHNcbiAgICBzaGltLmV4cG9ydHMgPSBleHBvcnRzO1xuICB9XG5cbiAgKGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAvKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbmlmKCFHTE1BVF9FUFNJTE9OKSB7XG4gICAgdmFyIEdMTUFUX0VQU0lMT04gPSAwLjAwMDAwMTtcbn1cblxuaWYoIUdMTUFUX0FSUkFZX1RZUEUpIHtcbiAgICB2YXIgR0xNQVRfQVJSQVlfVFlQRSA9ICh0eXBlb2YgRmxvYXQzMkFycmF5ICE9PSAndW5kZWZpbmVkJykgPyBGbG9hdDMyQXJyYXkgOiBBcnJheTtcbn1cblxuaWYoIUdMTUFUX1JBTkRPTSkge1xuICAgIHZhciBHTE1BVF9SQU5ET00gPSBNYXRoLnJhbmRvbTtcbn1cblxuLyoqXG4gKiBAY2xhc3MgQ29tbW9uIHV0aWxpdGllc1xuICogQG5hbWUgZ2xNYXRyaXhcbiAqL1xudmFyIGdsTWF0cml4ID0ge307XG5cbi8qKlxuICogU2V0cyB0aGUgdHlwZSBvZiBhcnJheSB1c2VkIHdoZW4gY3JlYXRpbmcgbmV3IHZlY3RvcnMgYW5kIG1hdHJpY2llc1xuICpcbiAqIEBwYXJhbSB7VHlwZX0gdHlwZSBBcnJheSB0eXBlLCBzdWNoIGFzIEZsb2F0MzJBcnJheSBvciBBcnJheVxuICovXG5nbE1hdHJpeC5zZXRNYXRyaXhBcnJheVR5cGUgPSBmdW5jdGlvbih0eXBlKSB7XG4gICAgR0xNQVRfQVJSQVlfVFlQRSA9IHR5cGU7XG59XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLmdsTWF0cml4ID0gZ2xNYXRyaXg7XG59XG5cbnZhciBkZWdyZWUgPSBNYXRoLlBJIC8gMTgwO1xuXG4vKipcbiogQ29udmVydCBEZWdyZWUgVG8gUmFkaWFuXG4qXG4qIEBwYXJhbSB7TnVtYmVyfSBBbmdsZSBpbiBEZWdyZWVzXG4qL1xuZ2xNYXRyaXgudG9SYWRpYW4gPSBmdW5jdGlvbihhKXtcbiAgICAgcmV0dXJuIGEgKiBkZWdyZWU7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyIERpbWVuc2lvbmFsIFZlY3RvclxuICogQG5hbWUgdmVjMlxuICovXG5cbnZhciB2ZWMyID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldywgZW1wdHkgdmVjMlxuICpcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gMDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgyKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzIgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHkpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLmFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnN1YnRyYWN0ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAtIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnN1YnRyYWN0fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuc3ViID0gdmVjMi5zdWJ0cmFjdDtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICogYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5tdWwgPSB2ZWMyLm11bHRpcGx5O1xuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5kaXZpZGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC8gYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdIC8gYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIuZGl2aWRlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGl2ID0gdmVjMi5kaXZpZGU7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWluaW11bSBvZiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLm1pbiA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pO1xuICAgIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5tYXggPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1heChhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgYSB2ZWMyIGJ5IGEgc2NhbGFyIG51bWJlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiO1xuICAgIG91dFsxXSA9IGFbMV0gKiBiO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzIncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnNjYWxlQW5kQWRkID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBzY2FsZSkge1xuICAgIG91dFswXSA9IGFbMF0gKyAoYlswXSAqIHNjYWxlKTtcbiAgICBvdXRbMV0gPSBhWzFdICsgKGJbMV0gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzIuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdO1xuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5KTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLmRpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGlzdCA9IHZlYzIuZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG52ZWMyLnNxdWFyZWREaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLnNxckRpc3QgPSB2ZWMyLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMyLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMi5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5sZW4gPSB2ZWMyLmxlbmd0aDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG52ZWMyLnNxdWFyZWRMZW5ndGggPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5zcXJMZW4gPSB2ZWMyLnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMyLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV07XG59O1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMyJ3NcbiAqIE5vdGUgdGhhdCB0aGUgY3Jvc3MgcHJvZHVjdCBtdXN0IGJ5IGRlZmluaXRpb24gcHJvZHVjZSBhIDNEIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMi5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciB6ID0gYVswXSAqIGJbMV0gLSBhWzFdICogYlswXTtcbiAgICBvdXRbMF0gPSBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IHo7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV07XG4gICAgb3V0WzBdID0gYXggKyB0ICogKGJbMF0gLSBheCk7XG4gICAgb3V0WzFdID0gYXkgKyB0ICogKGJbMV0gLSBheSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5yYW5kb20gPSBmdW5jdGlvbiAob3V0LCBzY2FsZSkge1xuICAgIHNjYWxlID0gc2NhbGUgfHwgMS4wO1xuICAgIHZhciByID0gR0xNQVRfUkFORE9NKCkgKiAyLjAgKiBNYXRoLlBJO1xuICAgIG91dFswXSA9IE1hdGguY29zKHIpICogc2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiBzY2FsZTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQyfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDIgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHk7XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzNdICogeTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyZFxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0MmR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIudHJhbnNmb3JtTWF0MmQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDNcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzEnXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQzfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDMgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVszXSAqIHkgKyBtWzZdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs0XSAqIHkgKyBtWzddO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDRcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzAnXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCBcbiAgICAgICAgeSA9IGFbMV07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bMTJdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzEzXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjMnMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMi4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzJzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzIuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gdmVjIHZlY3RvciB0byByZXByZXNlbnQgYXMgYSBzdHJpbmdcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmVjdG9yXG4gKi9cbnZlYzIuc3RyID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gJ3ZlYzIoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzIgPSB2ZWMyO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgMyBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzNcbiAqL1xuXG52YXIgdmVjMyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbnZlYzMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDMpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMyBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMyk7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgzKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjMyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzIHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnNldCA9IGZ1bmN0aW9uKG91dCwgeCwgeSwgeikge1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnN1YiA9IHZlYzMuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubXVsID0gdmVjMy5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpdiA9IHZlYzMuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5kaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeik7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpc3QgPSB2ZWMzLmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl07XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqejtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckRpc3QgPSB2ZWMzLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMzLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl07XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnopO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubGVuID0gdmVjMy5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjMy5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMuc3F1YXJlZExlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckxlbiA9IHZlYzMuc3F1YXJlZExlbmd0aDtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm5lZ2F0ZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IC1hWzBdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5ub3JtYWxpemUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5ICsgeip6O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMzLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTtcbn07XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdO1xuXG4gICAgb3V0WzBdID0gYXkgKiBieiAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV0sXG4gICAgICAgIGF6ID0gYVsyXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICB2YXIgciA9IEdMTUFUX1JBTkRPTSgpICogMi4wICogTWF0aC5QSTtcbiAgICB2YXIgeiA9IChHTE1BVF9SQU5ET00oKSAqIDIuMCkgLSAxLjA7XG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlO1xuXG4gICAgb3V0WzBdID0gTWF0aC5jb3MocikgKiB6U2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiB6U2NhbGU7XG4gICAgb3V0WzJdID0geiAqIHNjYWxlO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl07XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM107XG4gICAgb3V0WzJdID0gbVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMudHJhbnNmb3JtTWF0MyA9IGZ1bmN0aW9uKG91dCwgYSwgbSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdO1xuICAgIG91dFswXSA9IHggKiBtWzBdICsgeSAqIG1bM10gKyB6ICogbVs2XTtcbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN107XG4gICAgb3V0WzJdID0geCAqIG1bMl0gKyB5ICogbVs1XSArIHogKiBtWzhdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnRyYW5zZm9ybVF1YXQgPSBmdW5jdGlvbihvdXQsIGEsIHEpIHtcbiAgICAvLyBiZW5jaG1hcmtzOiBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXRyYW5zZm9ybS12ZWMzLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl0sXG4gICAgICAgIHF4ID0gcVswXSwgcXkgPSBxWzFdLCBxeiA9IHFbMl0sIHF3ID0gcVszXSxcblxuICAgICAgICAvLyBjYWxjdWxhdGUgcXVhdCAqIHZlY1xuICAgICAgICBpeCA9IHF3ICogeCArIHF5ICogeiAtIHF6ICogeSxcbiAgICAgICAgaXkgPSBxdyAqIHkgKyBxeiAqIHggLSBxeCAqIHosXG4gICAgICAgIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4LFxuICAgICAgICBpdyA9IC1xeCAqIHggLSBxeSAqIHkgLSBxeiAqIHo7XG5cbiAgICAvLyBjYWxjdWxhdGUgcmVzdWx0ICogaW52ZXJzZSBxdWF0XG4gICAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeTtcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6O1xuICAgIG91dFsyXSA9IGl6ICogcXcgKyBpdyAqIC1xeiArIGl4ICogLXF5IC0gaXkgKiAtcXg7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHgtYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVggPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICAgdmFyIHAgPSBbXSwgcj1bXTtcblx0ICAvL1RyYW5zbGF0ZSBwb2ludCB0byB0aGUgb3JpZ2luXG5cdCAgcFswXSA9IGFbMF0gLSBiWzBdO1xuXHQgIHBbMV0gPSBhWzFdIC0gYlsxXTtcbiAgXHRwWzJdID0gYVsyXSAtIGJbMl07XG5cblx0ICAvL3BlcmZvcm0gcm90YXRpb25cblx0ICByWzBdID0gcFswXTtcblx0ICByWzFdID0gcFsxXSpNYXRoLmNvcyhjKSAtIHBbMl0qTWF0aC5zaW4oYyk7XG5cdCAgclsyXSA9IHBbMV0qTWF0aC5zaW4oYykgKyBwWzJdKk1hdGguY29zKGMpO1xuXG5cdCAgLy90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuXHQgIG91dFswXSA9IHJbMF0gKyBiWzBdO1xuXHQgIG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuXHQgIG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuXG4gIFx0cmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHktYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVkgPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICBcdHZhciBwID0gW10sIHI9W107XG4gIFx0Ly9UcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICBcdHBbMF0gPSBhWzBdIC0gYlswXTtcbiAgXHRwWzFdID0gYVsxXSAtIGJbMV07XG4gIFx0cFsyXSA9IGFbMl0gLSBiWzJdO1xuICBcbiAgXHQvL3BlcmZvcm0gcm90YXRpb25cbiAgXHRyWzBdID0gcFsyXSpNYXRoLnNpbihjKSArIHBbMF0qTWF0aC5jb3MoYyk7XG4gIFx0clsxXSA9IHBbMV07XG4gIFx0clsyXSA9IHBbMl0qTWF0aC5jb3MoYykgLSBwWzBdKk1hdGguc2luKGMpO1xuICBcbiAgXHQvL3RyYW5zbGF0ZSB0byBjb3JyZWN0IHBvc2l0aW9uXG4gIFx0b3V0WzBdID0gclswXSArIGJbMF07XG4gIFx0b3V0WzFdID0gclsxXSArIGJbMV07XG4gIFx0b3V0WzJdID0gclsyXSArIGJbMl07XG4gIFxuICBcdHJldHVybiBvdXQ7XG59O1xuXG4vKlxuKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB6LWF4aXNcbiogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4qIEBwYXJhbSB7dmVjM30gYSBUaGUgdmVjMyBwb2ludCB0byByb3RhdGVcbiogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4qIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuKiBAcmV0dXJucyB7dmVjM30gb3V0XG4qL1xudmVjMy5yb3RhdGVaID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBjKXtcbiAgXHR2YXIgcCA9IFtdLCByPVtdO1xuICBcdC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgXHRwWzBdID0gYVswXSAtIGJbMF07XG4gIFx0cFsxXSA9IGFbMV0gLSBiWzFdO1xuICBcdHBbMl0gPSBhWzJdIC0gYlsyXTtcbiAgXG4gIFx0Ly9wZXJmb3JtIHJvdGF0aW9uXG4gIFx0clswXSA9IHBbMF0qTWF0aC5jb3MoYykgLSBwWzFdKk1hdGguc2luKGMpO1xuICBcdHJbMV0gPSBwWzBdKk1hdGguc2luKGMpICsgcFsxXSpNYXRoLmNvcyhjKTtcbiAgXHRyWzJdID0gcFsyXTtcbiAgXG4gIFx0Ly90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuICBcdG91dFswXSA9IHJbMF0gKyBiWzBdO1xuICBcdG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuICBcdG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuICBcbiAgXHRyZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjM3MuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMy4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzNzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzMuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07IHZlY1syXSA9IGFbaSsyXTtcbiAgICAgICAgICAgIGZuKHZlYywgdmVjLCBhcmcpO1xuICAgICAgICAgICAgYVtpXSA9IHZlY1swXTsgYVtpKzFdID0gdmVjWzFdOyBhW2krMl0gPSB2ZWNbMl07XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWMzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWMzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzMgPSB2ZWMzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNCBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzRcbiAqL1xuXG52YXIgdmVjNCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbnZlYzQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWM0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmZyb21WYWx1ZXMgPSBmdW5jdGlvbih4LCB5LCB6LCB3KSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIG91dFszXSA9IHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHksIHosIHcpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSB3O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICBvdXRbM10gPSBhWzNdICsgYlszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIG91dFszXSA9IGFbM10gLSBiWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LnN1YiA9IHZlYzQuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0Lm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAqIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubXVsID0gdmVjNC5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAvIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpdiA9IHZlYzQuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICBvdXRbM10gPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICBvdXRbM10gPSBhWzNdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICBvdXRbM10gPSBhWzNdICsgKGJbM10gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzQuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeiArIHcqdyk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpc3QgPSB2ZWM0LmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjNC5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6ICsgdyp3O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3F1YXJlZERpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuc3FyRGlzdCA9IHZlYzQuc3F1YXJlZERpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbnZlYzQubGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnogKyB3KncpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubGVuID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjNC5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqeiArIHcqdztcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjNC5zcXJMZW4gPSB2ZWM0LnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICBvdXRbMl0gPSAtYVsyXTtcbiAgICBvdXRbM10gPSAtYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl0sXG4gICAgICAgIHcgPSBhWzNdO1xuICAgIHZhciBsZW4gPSB4KnggKyB5KnkgKyB6KnogKyB3Knc7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pO1xuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuO1xuICAgICAgICBvdXRbMV0gPSBhWzFdICogbGVuO1xuICAgICAgICBvdXRbMl0gPSBhWzJdICogbGVuO1xuICAgICAgICBvdXRbM10gPSBhWzNdICogbGVuO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbnZlYzQuZG90ID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM107XG59O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LmxlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl0sXG4gICAgICAgIGF3ID0gYVszXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICAvL1RPRE86IFRoaXMgaXMgYSBwcmV0dHkgYXdmdWwgd2F5IG9mIGRvaW5nIHRoaXMuIEZpbmQgc29tZXRoaW5nIGJldHRlci5cbiAgICBvdXRbMF0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMV0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMl0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbM10gPSBHTE1BVF9SQU5ET00oKTtcbiAgICB2ZWM0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgdmVjNC5zY2FsZShvdXQsIG91dCwgc2NhbGUpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzQgd2l0aCBhIG1hdDQuXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnRyYW5zZm9ybU1hdDQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM107XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogdztcbiAgICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3O1xuICAgIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7cXVhdH0gcSBxdWF0ZXJuaW9uIHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQudHJhbnNmb3JtUXVhdCA9IGZ1bmN0aW9uKG91dCwgYSwgcSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLFxuICAgICAgICBxeCA9IHFbMF0sIHF5ID0gcVsxXSwgcXogPSBxWzJdLCBxdyA9IHFbM10sXG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHF1YXQgKiB2ZWNcbiAgICAgICAgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHksXG4gICAgICAgIGl5ID0gcXcgKiB5ICsgcXogKiB4IC0gcXggKiB6LFxuICAgICAgICBpeiA9IHF3ICogeiArIHF4ICogeSAtIHF5ICogeCxcbiAgICAgICAgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6O1xuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXk7XG4gICAgb3V0WzFdID0gaXkgKiBxdyArIGl3ICogLXF5ICsgaXogKiAtcXggLSBpeCAqIC1xejtcbiAgICBvdXRbMl0gPSBpeiAqIHF3ICsgaXcgKiAtcXogKyBpeCAqIC1xeSAtIGl5ICogLXF4O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFBlcmZvcm0gc29tZSBvcGVyYXRpb24gb3ZlciBhbiBhcnJheSBvZiB2ZWM0cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhIHRoZSBhcnJheSBvZiB2ZWN0b3JzIHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIHtOdW1iZXJ9IHN0cmlkZSBOdW1iZXIgb2YgZWxlbWVudHMgYmV0d2VlbiB0aGUgc3RhcnQgb2YgZWFjaCB2ZWM0LiBJZiAwIGFzc3VtZXMgdGlnaHRseSBwYWNrZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXQgTnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNraXAgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudCBOdW1iZXIgb2YgdmVjMnMgdG8gaXRlcmF0ZSBvdmVyLiBJZiAwIGl0ZXJhdGVzIG92ZXIgZW50aXJlIGFycmF5XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbYXJnXSBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHBhc3MgdG8gZm5cbiAqIEByZXR1cm5zIHtBcnJheX0gYVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuZm9yRWFjaCA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdmVjID0gdmVjNC5jcmVhdGUoKTtcblxuICAgIHJldHVybiBmdW5jdGlvbihhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGlmKCFzdHJpZGUpIHtcbiAgICAgICAgICAgIHN0cmlkZSA9IDQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZighb2Zmc2V0KSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGwgPSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gb2Zmc2V0OyBpIDwgbDsgaSArPSBzdHJpZGUpIHtcbiAgICAgICAgICAgIHZlY1swXSA9IGFbaV07IHZlY1sxXSA9IGFbaSsxXTsgdmVjWzJdID0gYVtpKzJdOyB2ZWNbM10gPSBhW2krM107XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTsgYVtpKzJdID0gdmVjWzJdOyBhW2krM10gPSB2ZWNbM107XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWM0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWM0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMudmVjNCA9IHZlYzQ7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDIgTWF0cml4XG4gKiBAbmFtZSBtYXQyXG4gKi9cblxudmFyIG1hdDIgPSB7fTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGlkZW50aXR5IG1hdDJcbiAqXG4gKiBAcmV0dXJucyB7bWF0Mn0gYSBuZXcgMngyIG1hdHJpeFxuICovXG5tYXQyLmNyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSAxO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSBtYXRyaXggdG8gY2xvbmVcbiAqIEByZXR1cm5zIHttYXQyfSBhIG5ldyAyeDIgbWF0cml4XG4gKi9cbm1hdDIuY2xvbmUgPSBmdW5jdGlvbihhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqL1xubWF0Mi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQyIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGExID0gYVsxXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYVsxXTtcbiAgICAgICAgb3V0WzNdID0gYVszXTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGEwICogYTMgLSBhMiAqIGExO1xuXG4gICAgaWYgKCFkZXQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcbiAgICBcbiAgICBvdXRbMF0gPSAgYTMgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWExICogZGV0O1xuICAgIG91dFsyXSA9IC1hMiAqIGRldDtcbiAgICBvdXRbM10gPSAgYTAgKiBkZXQ7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhZGp1Z2F0ZSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuYWRqb2ludCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIENhY2hpbmcgdGhpcyB2YWx1ZSBpcyBuZXNzZWNhcnkgaWYgb3V0ID09IGFcbiAgICB2YXIgYTAgPSBhWzBdO1xuICAgIG91dFswXSA9ICBhWzNdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIG91dFszXSA9ICBhMDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MlxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQyLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzJdICogYVsxXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MidzXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM107XG4gICAgdmFyIGIwID0gYlswXSwgYjEgPSBiWzFdLCBiMiA9IGJbMl0sIGIzID0gYlszXTtcbiAgICBvdXRbMF0gPSBhMCAqIGIwICsgYTIgKiBiMTtcbiAgICBvdXRbMV0gPSBhMSAqIGIwICsgYTMgKiBiMTtcbiAgICBvdXRbMl0gPSBhMCAqIGIyICsgYTIgKiBiMztcbiAgICBvdXRbM10gPSBhMSAqIGIyICsgYTMgKiBiMztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0Mi5tdWwgPSBtYXQyLm11bHRpcGx5O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQyIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIucm90YXRlID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICAgIG91dFswXSA9IGEwICogIGMgKyBhMiAqIHM7XG4gICAgb3V0WzFdID0gYTEgKiAgYyArIGEzICogcztcbiAgICBvdXRbMl0gPSBhMCAqIC1zICsgYTIgKiBjO1xuICAgIG91dFszXSA9IGExICogLXMgKyBhMyAqIGM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQyIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMyfSB2IHRoZSB2ZWMyIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqKi9cbm1hdDIuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIHYpIHtcbiAgICB2YXIgYTAgPSBhWzBdLCBhMSA9IGFbMV0sIGEyID0gYVsyXSwgYTMgPSBhWzNdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMCAqIHYwO1xuICAgIG91dFsxXSA9IGExICogdjA7XG4gICAgb3V0WzJdID0gYTIgKiB2MTtcbiAgICBvdXRbM10gPSBhMyAqIHYxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQyXG4gKlxuICogQHBhcmFtIHttYXQyfSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0Mi5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MignICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byBjYWxjdWxhdGUgRnJvYmVuaXVzIG5vcm0gb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IEZyb2Jlbml1cyBub3JtXG4gKi9cbm1hdDIuZnJvYiA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuKE1hdGguc3FydChNYXRoLnBvdyhhWzBdLCAyKSArIE1hdGgucG93KGFbMV0sIDIpICsgTWF0aC5wb3coYVsyXSwgMikgKyBNYXRoLnBvdyhhWzNdLCAyKSkpXG59O1xuXG4vKipcbiAqIFJldHVybnMgTCwgRCBhbmQgVSBtYXRyaWNlcyAoTG93ZXIgdHJpYW5ndWxhciwgRGlhZ29uYWwgYW5kIFVwcGVyIHRyaWFuZ3VsYXIpIGJ5IGZhY3Rvcml6aW5nIHRoZSBpbnB1dCBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gTCB0aGUgbG93ZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IEQgdGhlIGRpYWdvbmFsIG1hdHJpeCBcbiAqIEBwYXJhbSB7bWF0Mn0gVSB0aGUgdXBwZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIGlucHV0IG1hdHJpeCB0byBmYWN0b3JpemVcbiAqL1xuXG5tYXQyLkxEVSA9IGZ1bmN0aW9uIChMLCBELCBVLCBhKSB7IFxuICAgIExbMl0gPSBhWzJdL2FbMF07IFxuICAgIFVbMF0gPSBhWzBdOyBcbiAgICBVWzFdID0gYVsxXTsgXG4gICAgVVszXSA9IGFbM10gLSBMWzJdICogVVsxXTsgXG4gICAgcmV0dXJuIFtMLCBELCBVXTsgICAgICAgXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MiA9IG1hdDI7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDMgTWF0cml4XG4gKiBAbmFtZSBtYXQyZFxuICogXG4gKiBAZGVzY3JpcHRpb24gXG4gKiBBIG1hdDJkIGNvbnRhaW5zIHNpeCBlbGVtZW50cyBkZWZpbmVkIGFzOlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eV1cbiAqIDwvcHJlPlxuICogVGhpcyBpcyBhIHNob3J0IGZvcm0gZm9yIHRoZSAzeDMgbWF0cml4OlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eSxcbiAqICAwLCAwLCAxXVxuICogPC9wcmU+XG4gKiBUaGUgbGFzdCByb3cgaXMgaWdub3JlZCBzbyB0aGUgYXJyYXkgaXMgc2hvcnRlciBhbmQgb3BlcmF0aW9ucyBhcmUgZmFzdGVyLlxuICovXG5cbnZhciBtYXQyZCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0MmRcbiAqXG4gKiBAcmV0dXJucyB7bWF0MmR9IGEgbmV3IDJ4MyBtYXRyaXhcbiAqL1xubWF0MmQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MmQgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDJkfSBhIG5ldyAyeDMgbWF0cml4XG4gKi9cbm1hdDJkLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg2KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MmQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqL1xubWF0MmQuY29weSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCBhIG1hdDJkIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0MmR9IG91dFxuICovXG5tYXQyZC5pbnZlcnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYWEgPSBhWzBdLCBhYiA9IGFbMV0sIGFjID0gYVsyXSwgYWQgPSBhWzNdLFxuICAgICAgICBhdHggPSBhWzRdLCBhdHkgPSBhWzVdO1xuXG4gICAgdmFyIGRldCA9IGFhICogYWQgLSBhYiAqIGFjO1xuICAgIGlmKCFkZXQpe1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYWQgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWFiICogZGV0O1xuICAgIG91dFsyXSA9IC1hYyAqIGRldDtcbiAgICBvdXRbM10gPSBhYSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYWMgKiBhdHkgLSBhZCAqIGF0eCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKGFiICogYXR4IC0gYWEgKiBhdHkpICogZGV0O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MmRcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDJkLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzFdICogYVsyXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MmQnc1xuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyZH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBiMCA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM10sIGI0ID0gYls0XSwgYjUgPSBiWzVdO1xuICAgIG91dFswXSA9IGEwICogYjAgKyBhMiAqIGIxO1xuICAgIG91dFsxXSA9IGExICogYjAgKyBhMyAqIGIxO1xuICAgIG91dFsyXSA9IGEwICogYjIgKyBhMiAqIGIzO1xuICAgIG91dFszXSA9IGExICogYjIgKyBhMyAqIGIzO1xuICAgIG91dFs0XSA9IGEwICogYjQgKyBhMiAqIGI1ICsgYTQ7XG4gICAgb3V0WzVdID0gYTEgKiBiNCArIGEzICogYjUgKyBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDJkLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDJkLm11bCA9IG1hdDJkLm11bHRpcGx5O1xuXG5cbi8qKlxuICogUm90YXRlcyBhIG1hdDJkIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgb3V0WzBdID0gYTAgKiAgYyArIGEyICogcztcbiAgICBvdXRbMV0gPSBhMSAqICBjICsgYTMgKiBzO1xuICAgIG91dFsyXSA9IGEwICogLXMgKyBhMiAqIGM7XG4gICAgb3V0WzNdID0gYTEgKiAtcyArIGEzICogYztcbiAgICBvdXRbNF0gPSBhNDtcbiAgICBvdXRbNV0gPSBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDJkIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnNjYWxlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSwgYTQgPSBhWzRdLCBhNSA9IGFbNV0sXG4gICAgICAgIHYwID0gdlswXSwgdjEgPSB2WzFdO1xuICAgIG91dFswXSA9IGEwICogdjA7XG4gICAgb3V0WzFdID0gYTEgKiB2MDtcbiAgICBvdXRbMl0gPSBhMiAqIHYxO1xuICAgIG91dFszXSA9IGEzICogdjE7XG4gICAgb3V0WzRdID0gYTQ7XG4gICAgb3V0WzVdID0gYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNsYXRlcyB0aGUgbWF0MmQgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB0aGUgdmVjMiB0byB0cmFuc2xhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMDtcbiAgICBvdXRbMV0gPSBhMTtcbiAgICBvdXRbMl0gPSBhMjtcbiAgICBvdXRbM10gPSBhMztcbiAgICBvdXRbNF0gPSBhMCAqIHYwICsgYTIgKiB2MSArIGE0O1xuICAgIG91dFs1XSA9IGExICogdjAgKyBhMyAqIHYxICsgYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQyZC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MmQoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcsICcgKyBhWzJdICsgJywgJyArIFxuICAgICAgICAgICAgICAgICAgICBhWzNdICsgJywgJyArIGFbNF0gKyAnLCAnICsgYVs1XSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0MmQuZnJvYiA9IGZ1bmN0aW9uIChhKSB7IFxuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgMSkpXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MmQgPSBtYXQyZDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIDN4MyBNYXRyaXhcbiAqIEBuYW1lIG1hdDNcbiAqL1xuXG52YXIgbWF0MyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0M1xuICpcbiAqIEByZXR1cm5zIHttYXQzfSBhIG5ldyAzeDMgbWF0cml4XG4gKi9cbm1hdDMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDkpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMTtcbiAgICBvdXRbNV0gPSAwO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENvcGllcyB0aGUgdXBwZXItbGVmdCAzeDMgdmFsdWVzIGludG8gdGhlIGdpdmVuIG1hdDMuXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyAzeDMgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgICB0aGUgc291cmNlIDR4NCBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xubWF0My5mcm9tTWF0NCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbNF07XG4gICAgb3V0WzRdID0gYVs1XTtcbiAgICBvdXRbNV0gPSBhWzZdO1xuICAgIG91dFs2XSA9IGFbOF07XG4gICAgb3V0WzddID0gYVs5XTtcbiAgICBvdXRbOF0gPSBhWzEwXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IG1hdDMgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IGEgbWF0cml4IHRvIGNsb25lXG4gKiBAcmV0dXJucyB7bWF0M30gYSBuZXcgM3gzIG1hdHJpeFxuICovXG5tYXQzLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg5KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQzIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAxO1xuICAgIG91dFs1XSA9IDA7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNwb3NlIHRoZSB2YWx1ZXMgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnRyYW5zcG9zZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgICBpZiAob3V0ID09PSBhKSB7XG4gICAgICAgIHZhciBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMTIgPSBhWzVdO1xuICAgICAgICBvdXRbMV0gPSBhWzNdO1xuICAgICAgICBvdXRbMl0gPSBhWzZdO1xuICAgICAgICBvdXRbM10gPSBhMDE7XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGEwMjtcbiAgICAgICAgb3V0WzddID0gYTEyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFswXSA9IGFbMF07XG4gICAgICAgIG91dFsxXSA9IGFbM107XG4gICAgICAgIG91dFsyXSA9IGFbNl07XG4gICAgICAgIG91dFszXSA9IGFbMV07XG4gICAgICAgIG91dFs0XSA9IGFbNF07XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGFbMl07XG4gICAgICAgIG91dFs3XSA9IGFbNV07XG4gICAgICAgIG91dFs4XSA9IGFbOF07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmludmVydCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIGIwMSA9IGEyMiAqIGExMSAtIGExMiAqIGEyMSxcbiAgICAgICAgYjExID0gLWEyMiAqIGExMCArIGExMiAqIGEyMCxcbiAgICAgICAgYjIxID0gYTIxICogYTEwIC0gYTExICogYTIwLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYjAxICogZGV0O1xuICAgIG91dFsxXSA9ICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldDtcbiAgICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldDtcbiAgICBvdXRbM10gPSBiMTEgKiBkZXQ7XG4gICAgb3V0WzRdID0gKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0O1xuICAgIG91dFs2XSA9IGIyMSAqIGRldDtcbiAgICBvdXRbN10gPSAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQ7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIG91dFswXSA9IChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpO1xuICAgIG91dFsxXSA9IChhMDIgKiBhMjEgLSBhMDEgKiBhMjIpO1xuICAgIG91dFsyXSA9IChhMDEgKiBhMTIgLSBhMDIgKiBhMTEpO1xuICAgIG91dFszXSA9IChhMTIgKiBhMjAgLSBhMTAgKiBhMjIpO1xuICAgIG91dFs0XSA9IChhMDAgKiBhMjIgLSBhMDIgKiBhMjApO1xuICAgIG91dFs1XSA9IChhMDIgKiBhMTAgLSBhMDAgKiBhMTIpO1xuICAgIG91dFs2XSA9IChhMTAgKiBhMjEgLSBhMTEgKiBhMjApO1xuICAgIG91dFs3XSA9IChhMDEgKiBhMjAgLSBhMDAgKiBhMjEpO1xuICAgIG91dFs4XSA9IChhMDAgKiBhMTEgLSBhMDEgKiBhMTApO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQzLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIHJldHVybiBhMDAgKiAoYTIyICogYTExIC0gYTEyICogYTIxKSArIGEwMSAqICgtYTIyICogYTEwICsgYTEyICogYTIwKSArIGEwMiAqIChhMjEgKiBhMTAgLSBhMTEgKiBhMjApO1xufTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQzJ3NcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge21hdDN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMubXVsdGlwbHkgPSBmdW5jdGlvbiAob3V0LCBhLCBiKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG5cbiAgICAgICAgYjAwID0gYlswXSwgYjAxID0gYlsxXSwgYjAyID0gYlsyXSxcbiAgICAgICAgYjEwID0gYlszXSwgYjExID0gYls0XSwgYjEyID0gYls1XSxcbiAgICAgICAgYjIwID0gYls2XSwgYjIxID0gYls3XSwgYjIyID0gYls4XTtcblxuICAgIG91dFswXSA9IGIwMCAqIGEwMCArIGIwMSAqIGExMCArIGIwMiAqIGEyMDtcbiAgICBvdXRbMV0gPSBiMDAgKiBhMDEgKyBiMDEgKiBhMTEgKyBiMDIgKiBhMjE7XG4gICAgb3V0WzJdID0gYjAwICogYTAyICsgYjAxICogYTEyICsgYjAyICogYTIyO1xuXG4gICAgb3V0WzNdID0gYjEwICogYTAwICsgYjExICogYTEwICsgYjEyICogYTIwO1xuICAgIG91dFs0XSA9IGIxMCAqIGEwMSArIGIxMSAqIGExMSArIGIxMiAqIGEyMTtcbiAgICBvdXRbNV0gPSBiMTAgKiBhMDIgKyBiMTEgKiBhMTIgKyBiMTIgKiBhMjI7XG5cbiAgICBvdXRbNl0gPSBiMjAgKiBhMDAgKyBiMjEgKiBhMTAgKyBiMjIgKiBhMjA7XG4gICAgb3V0WzddID0gYjIwICogYTAxICsgYjIxICogYTExICsgYjIyICogYTIxO1xuICAgIG91dFs4XSA9IGIyMCAqIGEwMiArIGIyMSAqIGExMiArIGIyMiAqIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDMubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0My5tdWwgPSBtYXQzLm11bHRpcGx5O1xuXG4vKipcbiAqIFRyYW5zbGF0ZSBhIG1hdDMgYnkgdGhlIGdpdmVuIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDN9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMudHJhbnNsYXRlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG4gICAgICAgIHggPSB2WzBdLCB5ID0gdlsxXTtcblxuICAgIG91dFswXSA9IGEwMDtcbiAgICBvdXRbMV0gPSBhMDE7XG4gICAgb3V0WzJdID0gYTAyO1xuXG4gICAgb3V0WzNdID0gYTEwO1xuICAgIG91dFs0XSA9IGExMTtcbiAgICBvdXRbNV0gPSBhMTI7XG5cbiAgICBvdXRbNl0gPSB4ICogYTAwICsgeSAqIGExMCArIGEyMDtcbiAgICBvdXRbN10gPSB4ICogYTAxICsgeSAqIGExMSArIGEyMTtcbiAgICBvdXRbOF0gPSB4ICogYTAyICsgeSAqIGExMiArIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0MyBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKTtcblxuICAgIG91dFswXSA9IGMgKiBhMDAgKyBzICogYTEwO1xuICAgIG91dFsxXSA9IGMgKiBhMDEgKyBzICogYTExO1xuICAgIG91dFsyXSA9IGMgKiBhMDIgKyBzICogYTEyO1xuXG4gICAgb3V0WzNdID0gYyAqIGExMCAtIHMgKiBhMDA7XG4gICAgb3V0WzRdID0gYyAqIGExMSAtIHMgKiBhMDE7XG4gICAgb3V0WzVdID0gYyAqIGExMiAtIHMgKiBhMDI7XG5cbiAgICBvdXRbNl0gPSBhMjA7XG4gICAgb3V0WzddID0gYTIxO1xuICAgIG91dFs4XSA9IGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDMgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICoqL1xubWF0My5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV07XG5cbiAgICBvdXRbMF0gPSB4ICogYVswXTtcbiAgICBvdXRbMV0gPSB4ICogYVsxXTtcbiAgICBvdXRbMl0gPSB4ICogYVsyXTtcblxuICAgIG91dFszXSA9IHkgKiBhWzNdO1xuICAgIG91dFs0XSA9IHkgKiBhWzRdO1xuICAgIG91dFs1XSA9IHkgKiBhWzVdO1xuXG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29waWVzIHRoZSB2YWx1ZXMgZnJvbSBhIG1hdDJkIGludG8gYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byBjb3B5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKiovXG5tYXQzLmZyb21NYXQyZCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSAwO1xuXG4gICAgb3V0WzNdID0gYVsyXTtcbiAgICBvdXRbNF0gPSBhWzNdO1xuICAgIG91dFs1XSA9IDA7XG5cbiAgICBvdXRbNl0gPSBhWzRdO1xuICAgIG91dFs3XSA9IGFbNV07XG4gICAgb3V0WzhdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbWF0cml4IGZyb20gdGhlIGdpdmVuIHF1YXRlcm5pb25cbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge3F1YXR9IHEgUXVhdGVybmlvbiB0byBjcmVhdGUgbWF0cml4IGZyb21cbipcbiogQHJldHVybnMge21hdDN9IG91dFxuKi9cbm1hdDMuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbM10gPSB5eCAtIHd6O1xuICAgIG91dFs2XSA9IHp4ICsgd3k7XG5cbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFs0XSA9IDEgLSB4eCAtIHp6O1xuICAgIG91dFs3XSA9IHp5IC0gd3g7XG5cbiAgICBvdXRbMl0gPSB6eCAtIHd5O1xuICAgIG91dFs1XSA9IHp5ICsgd3g7XG4gICAgb3V0WzhdID0gMSAtIHh4IC0geXk7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbm9ybWFsIG1hdHJpeCAodHJhbnNwb3NlIGludmVyc2UpIGZyb20gdGhlIDR4NCBtYXRyaXhcbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge21hdDR9IGEgTWF0NCB0byBkZXJpdmUgdGhlIG5vcm1hbCBtYXRyaXggZnJvbVxuKlxuKiBAcmV0dXJucyB7bWF0M30gb3V0XG4qL1xubWF0My5ub3JtYWxGcm9tTWF0NCA9IGZ1bmN0aW9uIChvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XSxcblxuICAgICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXG4gICAgICAgIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMCxcbiAgICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxuICAgICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXG4gICAgICAgIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMSxcbiAgICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxuICAgICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXG4gICAgICAgIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMCxcbiAgICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxuICAgICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXG4gICAgICAgIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMSxcbiAgICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzFdID0gKGExMiAqIGIwOCAtIGExMCAqIGIxMSAtIGExMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzJdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG5cbiAgICBvdXRbM10gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcblxuICAgIG91dFs2XSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFs3XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG1hdCBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdtYXQzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVszXSArICcsICcgKyBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgXG4gICAgICAgICAgICAgICAgICAgIGFbNl0gKyAnLCAnICsgYVs3XSArICcsICcgKyBhWzhdICsgJyknO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIEZyb2Jlbml1cyBub3JtIG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0My5mcm9iID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4oTWF0aC5zcXJ0KE1hdGgucG93KGFbMF0sIDIpICsgTWF0aC5wb3coYVsxXSwgMikgKyBNYXRoLnBvdyhhWzJdLCAyKSArIE1hdGgucG93KGFbM10sIDIpICsgTWF0aC5wb3coYVs0XSwgMikgKyBNYXRoLnBvdyhhWzVdLCAyKSArIE1hdGgucG93KGFbNl0sIDIpICsgTWF0aC5wb3coYVs3XSwgMikgKyBNYXRoLnBvdyhhWzhdLCAyKSkpXG59O1xuXG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLm1hdDMgPSBtYXQzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNHg0IE1hdHJpeFxuICogQG5hbWUgbWF0NFxuICovXG5cbnZhciBtYXQ0ID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBpZGVudGl0eSBtYXQ0XG4gKlxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQ0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIG91dFs2XSA9IGFbNl07XG4gICAgb3V0WzddID0gYVs3XTtcbiAgICBvdXRbOF0gPSBhWzhdO1xuICAgIG91dFs5XSA9IGFbOV07XG4gICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgIG91dFsxMV0gPSBhWzExXTtcbiAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbNF0gPSBhWzRdO1xuICAgIG91dFs1XSA9IGFbNV07XG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQ0IHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgICAgICBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGEwMTtcbiAgICAgICAgb3V0WzZdID0gYVs5XTtcbiAgICAgICAgb3V0WzddID0gYVsxM107XG4gICAgICAgIG91dFs4XSA9IGEwMjtcbiAgICAgICAgb3V0WzldID0gYTEyO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhMDM7XG4gICAgICAgIG91dFsxM10gPSBhMTM7XG4gICAgICAgIG91dFsxNF0gPSBhMjM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGFbMV07XG4gICAgICAgIG91dFs1XSA9IGFbNV07XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhWzJdO1xuICAgICAgICBvdXRbOV0gPSBhWzZdO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbM107XG4gICAgICAgIG91dFsxM10gPSBhWzddO1xuICAgICAgICBvdXRbMTRdID0gYVsxMV07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV0sXG5cbiAgICAgICAgYjAwID0gYTAwICogYTExIC0gYTAxICogYTEwLFxuICAgICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXG4gICAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcbiAgICAgICAgYjAzID0gYTAxICogYTEyIC0gYTAyICogYTExLFxuICAgICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXG4gICAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcbiAgICAgICAgYjA2ID0gYTIwICogYTMxIC0gYTIxICogYTMwLFxuICAgICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXG4gICAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcbiAgICAgICAgYjA5ID0gYTIxICogYTMyIC0gYTIyICogYTMxLFxuICAgICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXG4gICAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMixcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcblxuICAgIGlmICghZGV0KSB7IFxuICAgICAgICByZXR1cm4gbnVsbDsgXG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcblxuICAgIG91dFswXSA9IChhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDkpICogZGV0O1xuICAgIG91dFsxXSA9IChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0O1xuICAgIG91dFsyXSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFszXSA9IChhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMpICogZGV0O1xuICAgIG91dFs0XSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICAgIG91dFs1XSA9IChhMDAgKiBiMTEgLSBhMDIgKiBiMDggKyBhMDMgKiBiMDcpICogZGV0O1xuICAgIG91dFs2XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs3XSA9IChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMTAgKiBiMTAgLSBhMTEgKiBiMDggKyBhMTMgKiBiMDYpICogZGV0O1xuICAgIG91dFs5XSA9IChhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYpICogZGV0O1xuICAgIG91dFsxMF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTFdID0gKGEyMSAqIGIwMiAtIGEyMCAqIGIwNCAtIGEyMyAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzEyXSA9IChhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYpICogZGV0O1xuICAgIG91dFsxM10gPSAoYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTRdID0gKGEzMSAqIGIwMSAtIGEzMCAqIGIwMyAtIGEzMiAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzE1XSA9IChhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XTtcblxuICAgIG91dFswXSAgPSAgKGExMSAqIChhMjIgKiBhMzMgLSBhMjMgKiBhMzIpIC0gYTIxICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgKyBhMzEgKiAoYTEyICogYTIzIC0gYTEzICogYTIyKSk7XG4gICAgb3V0WzFdICA9IC0oYTAxICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjEgKiAoYTAyICogYTMzIC0gYTAzICogYTMyKSArIGEzMSAqIChhMDIgKiBhMjMgLSBhMDMgKiBhMjIpKTtcbiAgICBvdXRbMl0gID0gIChhMDEgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSAtIGExMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGExMyAtIGEwMyAqIGExMikpO1xuICAgIG91dFszXSAgPSAtKGEwMSAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpIC0gYTExICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikgKyBhMjEgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzRdICA9IC0oYTEwICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjAgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSArIGEzMCAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpKTtcbiAgICBvdXRbNV0gID0gIChhMDAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMwICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikpO1xuICAgIG91dFs2XSAgPSAtKGEwMCAqIChhMTIgKiBhMzMgLSBhMTMgKiBhMzIpIC0gYTEwICogKGEwMiAqIGEzMyAtIGEwMyAqIGEzMikgKyBhMzAgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzddICA9ICAoYTAwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTAgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgICBvdXRbOF0gID0gIChhMTAgKiAoYTIxICogYTMzIC0gYTIzICogYTMxKSAtIGEyMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpICsgYTMwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSkpO1xuICAgIG91dFs5XSAgPSAtKGEwMCAqIChhMjEgKiBhMzMgLSBhMjMgKiBhMzEpIC0gYTIwICogKGEwMSAqIGEzMyAtIGEwMyAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTIzIC0gYTAzICogYTIxKSk7XG4gICAgb3V0WzEwXSA9ICAoYTAwICogKGExMSAqIGEzMyAtIGExMyAqIGEzMSkgLSBhMTAgKiAoYTAxICogYTMzIC0gYTAzICogYTMxKSArIGEzMCAqIChhMDEgKiBhMTMgLSBhMDMgKiBhMTEpKTtcbiAgICBvdXRbMTFdID0gLShhMDAgKiAoYTExICogYTIzIC0gYTEzICogYTIxKSAtIGExMCAqIChhMDEgKiBhMjMgLSBhMDMgKiBhMjEpICsgYTIwICogKGEwMSAqIGExMyAtIGEwMyAqIGExMSkpO1xuICAgIG91dFsxMl0gPSAtKGExMCAqIChhMjEgKiBhMzIgLSBhMjIgKiBhMzEpIC0gYTIwICogKGExMSAqIGEzMiAtIGExMiAqIGEzMSkgKyBhMzAgKiAoYTExICogYTIyIC0gYTEyICogYTIxKSk7XG4gICAgb3V0WzEzXSA9ICAoYTAwICogKGEyMSAqIGEzMiAtIGEyMiAqIGEzMSkgLSBhMjAgKiAoYTAxICogYTMyIC0gYTAyICogYTMxKSArIGEzMCAqIChhMDEgKiBhMjIgLSBhMDIgKiBhMjEpKTtcbiAgICBvdXRbMTRdID0gLShhMDAgKiAoYTExICogYTMyIC0gYTEyICogYTMxKSAtIGExMCAqIChhMDEgKiBhMzIgLSBhMDIgKiBhMzEpICsgYTMwICogKGEwMSAqIGExMiAtIGEwMiAqIGExMSkpO1xuICAgIG91dFsxNV0gPSAgKGEwMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpIC0gYTEwICogKGEwMSAqIGEyMiAtIGEwMiAqIGEyMSkgKyBhMjAgKiAoYTAxICogYTEyIC0gYTAyICogYTExKSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZGV0ZXJtaW5hbnQgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDQuZGV0ZXJtaW5hbnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgcmV0dXJuIGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0NCdzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0Lm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdO1xuXG4gICAgLy8gQ2FjaGUgb25seSB0aGUgY3VycmVudCBsaW5lIG9mIHRoZSBzZWNvbmQgbWF0cml4XG4gICAgdmFyIGIwICA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107ICBcbiAgICBvdXRbMF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzFdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsyXSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbM10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbNF07IGIxID0gYls1XTsgYjIgPSBiWzZdOyBiMyA9IGJbN107XG4gICAgb3V0WzRdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs1XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbNl0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzddID0gYjAqYTAzICsgYjEqYTEzICsgYjIqYTIzICsgYjMqYTMzO1xuXG4gICAgYjAgPSBiWzhdOyBiMSA9IGJbOV07IGIyID0gYlsxMF07IGIzID0gYlsxMV07XG4gICAgb3V0WzhdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs5XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTBdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxMV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbMTJdOyBiMSA9IGJbMTNdOyBiMiA9IGJbMTRdOyBiMyA9IGJbMTVdO1xuICAgIG91dFsxMl0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzEzXSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTRdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxNV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDQubXVsID0gbWF0NC5tdWx0aXBseTtcblxuLyoqXG4gKiBUcmFuc2xhdGUgYSBtYXQ0IGJ5IHRoZSBnaXZlbiB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdmVjdG9yIHRvIHRyYW5zbGF0ZSBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHYpIHtcbiAgICB2YXIgeCA9IHZbMF0sIHkgPSB2WzFdLCB6ID0gdlsyXSxcbiAgICAgICAgYTAwLCBhMDEsIGEwMiwgYTAzLFxuICAgICAgICBhMTAsIGExMSwgYTEyLCBhMTMsXG4gICAgICAgIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICAgIGlmIChhID09PSBvdXQpIHtcbiAgICAgICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzJdICogeCArIGFbNl0gKiB5ICsgYVsxMF0gKiB6ICsgYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICAgICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICAgICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFswXSA9IGEwMDsgb3V0WzFdID0gYTAxOyBvdXRbMl0gPSBhMDI7IG91dFszXSA9IGEwMztcbiAgICAgICAgb3V0WzRdID0gYTEwOyBvdXRbNV0gPSBhMTE7IG91dFs2XSA9IGExMjsgb3V0WzddID0gYTEzO1xuICAgICAgICBvdXRbOF0gPSBhMjA7IG91dFs5XSA9IGEyMTsgb3V0WzEwXSA9IGEyMjsgb3V0WzExXSA9IGEyMztcblxuICAgICAgICBvdXRbMTJdID0gYTAwICogeCArIGExMCAqIHkgKyBhMjAgKiB6ICsgYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhMDEgKiB4ICsgYTExICogeSArIGEyMSAqIHogKyBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYTAzICogeCArIGExMyAqIHkgKyBhMjMgKiB6ICsgYVsxNV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQ0IGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdGhlIHZlYzMgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICoqL1xubWF0NC5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV0sIHogPSB2WzJdO1xuXG4gICAgb3V0WzBdID0gYVswXSAqIHg7XG4gICAgb3V0WzFdID0gYVsxXSAqIHg7XG4gICAgb3V0WzJdID0gYVsyXSAqIHg7XG4gICAgb3V0WzNdID0gYVszXSAqIHg7XG4gICAgb3V0WzRdID0gYVs0XSAqIHk7XG4gICAgb3V0WzVdID0gYVs1XSAqIHk7XG4gICAgb3V0WzZdID0gYVs2XSAqIHk7XG4gICAgb3V0WzddID0gYVs3XSAqIHk7XG4gICAgb3V0WzhdID0gYVs4XSAqIHo7XG4gICAgb3V0WzldID0gYVs5XSAqIHo7XG4gICAgb3V0WzEwXSA9IGFbMTBdICogejtcbiAgICBvdXRbMTFdID0gYVsxMV0gKiB6O1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0NCBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGUgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQsIGF4aXMpIHtcbiAgICB2YXIgeCA9IGF4aXNbMF0sIHkgPSBheGlzWzFdLCB6ID0gYXhpc1syXSxcbiAgICAgICAgbGVuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiksXG4gICAgICAgIHMsIGMsIHQsXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjMsXG4gICAgICAgIGIwMCwgYjAxLCBiMDIsXG4gICAgICAgIGIxMCwgYjExLCBiMTIsXG4gICAgICAgIGIyMCwgYjIxLCBiMjI7XG5cbiAgICBpZiAoTWF0aC5hYnMobGVuKSA8IEdMTUFUX0VQU0lMT04pIHsgcmV0dXJuIG51bGw7IH1cbiAgICBcbiAgICBsZW4gPSAxIC8gbGVuO1xuICAgIHggKj0gbGVuO1xuICAgIHkgKj0gbGVuO1xuICAgIHogKj0gbGVuO1xuXG4gICAgcyA9IE1hdGguc2luKHJhZCk7XG4gICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgdCA9IDEgLSBjO1xuXG4gICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICBhMTAgPSBhWzRdOyBhMTEgPSBhWzVdOyBhMTIgPSBhWzZdOyBhMTMgPSBhWzddO1xuICAgIGEyMCA9IGFbOF07IGEyMSA9IGFbOV07IGEyMiA9IGFbMTBdOyBhMjMgPSBhWzExXTtcblxuICAgIC8vIENvbnN0cnVjdCB0aGUgZWxlbWVudHMgb2YgdGhlIHJvdGF0aW9uIG1hdHJpeFxuICAgIGIwMCA9IHggKiB4ICogdCArIGM7IGIwMSA9IHkgKiB4ICogdCArIHogKiBzOyBiMDIgPSB6ICogeCAqIHQgLSB5ICogcztcbiAgICBiMTAgPSB4ICogeSAqIHQgLSB6ICogczsgYjExID0geSAqIHkgKiB0ICsgYzsgYjEyID0geiAqIHkgKiB0ICsgeCAqIHM7XG4gICAgYjIwID0geCAqIHogKiB0ICsgeSAqIHM7IGIyMSA9IHkgKiB6ICogdCAtIHggKiBzOyBiMjIgPSB6ICogeiAqIHQgKyBjO1xuXG4gICAgLy8gUGVyZm9ybSByb3RhdGlvbi1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBiMDAgKyBhMTAgKiBiMDEgKyBhMjAgKiBiMDI7XG4gICAgb3V0WzFdID0gYTAxICogYjAwICsgYTExICogYjAxICsgYTIxICogYjAyO1xuICAgIG91dFsyXSA9IGEwMiAqIGIwMCArIGExMiAqIGIwMSArIGEyMiAqIGIwMjtcbiAgICBvdXRbM10gPSBhMDMgKiBiMDAgKyBhMTMgKiBiMDEgKyBhMjMgKiBiMDI7XG4gICAgb3V0WzRdID0gYTAwICogYjEwICsgYTEwICogYjExICsgYTIwICogYjEyO1xuICAgIG91dFs1XSA9IGEwMSAqIGIxMCArIGExMSAqIGIxMSArIGEyMSAqIGIxMjtcbiAgICBvdXRbNl0gPSBhMDIgKiBiMTAgKyBhMTIgKiBiMTEgKyBhMjIgKiBiMTI7XG4gICAgb3V0WzddID0gYTAzICogYjEwICsgYTEzICogYjExICsgYTIzICogYjEyO1xuICAgIG91dFs4XSA9IGEwMCAqIGIyMCArIGExMCAqIGIyMSArIGEyMCAqIGIyMjtcbiAgICBvdXRbOV0gPSBhMDEgKiBiMjAgKyBhMTEgKiBiMjEgKyBhMjEgKiBiMjI7XG4gICAgb3V0WzEwXSA9IGEwMiAqIGIyMCArIGExMiAqIGIyMSArIGEyMiAqIGIyMjtcbiAgICBvdXRbMTFdID0gYTAzICogYjIwICsgYTEzICogYjIxICsgYTIzICogYjIyO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGVYID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSxcbiAgICAgICAgYTIxID0gYVs5XSxcbiAgICAgICAgYTIyID0gYVsxMF0sXG4gICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgICAgIG91dFswXSAgPSBhWzBdO1xuICAgICAgICBvdXRbMV0gID0gYVsxXTtcbiAgICAgICAgb3V0WzJdICA9IGFbMl07XG4gICAgICAgIG91dFszXSAgPSBhWzNdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFs0XSA9IGExMCAqIGMgKyBhMjAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgKyBhMjIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgKyBhMjMgKiBzO1xuICAgIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICAgIG91dFs5XSA9IGEyMSAqIGMgLSBhMTEgKiBzO1xuICAgIG91dFsxMF0gPSBhMjIgKiBjIC0gYTEyICogcztcbiAgICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMjAgPSBhWzhdLFxuICAgICAgICBhMjEgPSBhWzldLFxuICAgICAgICBhMjIgPSBhWzEwXSxcbiAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIHJvd3NcbiAgICAgICAgb3V0WzRdICA9IGFbNF07XG4gICAgICAgIG91dFs1XSAgPSBhWzVdO1xuICAgICAgICBvdXRbNl0gID0gYVs2XTtcbiAgICAgICAgb3V0WzddICA9IGFbN107XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyAtIGEyMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyAtIGEyMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyAtIGEyMyAqIHM7XG4gICAgb3V0WzhdID0gYTAwICogcyArIGEyMCAqIGM7XG4gICAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gICAgb3V0WzEwXSA9IGEwMiAqIHMgKyBhMjIgKiBjO1xuICAgIG91dFsxMV0gPSBhMDMgKiBzICsgYTIzICogYztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQucm90YXRlWiA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGEwMCA9IGFbMF0sXG4gICAgICAgIGEwMSA9IGFbMV0sXG4gICAgICAgIGEwMiA9IGFbMl0sXG4gICAgICAgIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sXG4gICAgICAgIGExMSA9IGFbNV0sXG4gICAgICAgIGExMiA9IGFbNl0sXG4gICAgICAgIGExMyA9IGFbN107XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgICAgIG91dFs4XSAgPSBhWzhdO1xuICAgICAgICBvdXRbOV0gID0gYVs5XTtcbiAgICAgICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgICAgICBvdXRbMTFdID0gYVsxMV07XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyArIGExMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyArIGExMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyArIGExMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyArIGExMyAqIHM7XG4gICAgb3V0WzRdID0gYTEwICogYyAtIGEwMCAqIHM7XG4gICAgb3V0WzVdID0gYTExICogYyAtIGEwMSAqIHM7XG4gICAgb3V0WzZdID0gYTEyICogYyAtIGEwMiAqIHM7XG4gICAgb3V0WzddID0gYTEzICogYyAtIGEwMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiBhbmQgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIHZhciBxdWF0TWF0ID0gbWF0NC5jcmVhdGUoKTtcbiAqICAgICBxdWF0NC50b01hdDQocXVhdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5tdWx0aXBseShkZXN0LCBxdWF0TWF0KTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7dmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5mcm9tUm90YXRpb25UcmFuc2xhdGlvbiA9IGZ1bmN0aW9uIChvdXQsIHEsIHYpIHtcbiAgICAvLyBRdWF0ZXJuaW9uIG1hdGhcbiAgICB2YXIgeCA9IHFbMF0sIHkgPSBxWzFdLCB6ID0gcVsyXSwgdyA9IHFbM10sXG4gICAgICAgIHgyID0geCArIHgsXG4gICAgICAgIHkyID0geSArIHksXG4gICAgICAgIHoyID0geiArIHosXG5cbiAgICAgICAgeHggPSB4ICogeDIsXG4gICAgICAgIHh5ID0geCAqIHkyLFxuICAgICAgICB4eiA9IHggKiB6MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHl6ID0geSAqIHoyLFxuICAgICAgICB6eiA9IHogKiB6MixcbiAgICAgICAgd3ggPSB3ICogeDIsXG4gICAgICAgIHd5ID0gdyAqIHkyLFxuICAgICAgICB3eiA9IHcgKiB6MjtcblxuICAgIG91dFswXSA9IDEgLSAoeXkgKyB6eik7XG4gICAgb3V0WzFdID0geHkgKyB3ejtcbiAgICBvdXRbMl0gPSB4eiAtIHd5O1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0geHkgLSB3ejtcbiAgICBvdXRbNV0gPSAxIC0gKHh4ICsgenopO1xuICAgIG91dFs2XSA9IHl6ICsgd3g7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSB4eiArIHd5O1xuICAgIG91dFs5XSA9IHl6IC0gd3g7XG4gICAgb3V0WzEwXSA9IDEgLSAoeHggKyB5eSk7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IHZbMF07XG4gICAgb3V0WzEzXSA9IHZbMV07XG4gICAgb3V0WzE0XSA9IHZbMl07XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbm1hdDQuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFsyXSA9IHp4IC0gd3k7XG4gICAgb3V0WzNdID0gMDtcblxuICAgIG91dFs0XSA9IHl4IC0gd3o7XG4gICAgb3V0WzVdID0gMSAtIHh4IC0geno7XG4gICAgb3V0WzZdID0genkgKyB3eDtcbiAgICBvdXRbN10gPSAwO1xuXG4gICAgb3V0WzhdID0genggKyB3eTtcbiAgICBvdXRbOV0gPSB6eSAtIHd4O1xuICAgIG91dFsxMF0gPSAxIC0geHggLSB5eTtcbiAgICBvdXRbMTFdID0gMDtcblxuICAgIG91dFsxMl0gPSAwO1xuICAgIG91dFsxM10gPSAwO1xuICAgIG91dFsxNF0gPSAwO1xuICAgIG91dFsxNV0gPSAxO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgZnJ1c3R1bSBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtOdW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuZnJ1c3R1bSA9IGZ1bmN0aW9uIChvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIHJsID0gMSAvIChyaWdodCAtIGxlZnQpLFxuICAgICAgICB0YiA9IDEgLyAodG9wIC0gYm90dG9tKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IChuZWFyICogMikgKiBybDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IChuZWFyICogMikgKiB0YjtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gKHJpZ2h0ICsgbGVmdCkgKiBybDtcbiAgICBvdXRbOV0gPSAodG9wICsgYm90dG9tKSAqIHRiO1xuICAgIG91dFsxMF0gPSAoZmFyICsgbmVhcikgKiBuZjtcbiAgICBvdXRbMTFdID0gLTE7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IChmYXIgKiBuZWFyICogMikgKiBuZjtcbiAgICBvdXRbMTVdID0gMDtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge251bWJlcn0gZm92eSBWZXJ0aWNhbCBmaWVsZCBvZiB2aWV3IGluIHJhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhc3BlY3QgQXNwZWN0IHJhdGlvLiB0eXBpY2FsbHkgdmlld3BvcnQgd2lkdGgvaGVpZ2h0XG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnBlcnNwZWN0aXZlID0gZnVuY3Rpb24gKG91dCwgZm92eSwgYXNwZWN0LCBuZWFyLCBmYXIpIHtcbiAgICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IGYgLyBhc3BlY3Q7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSBmO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxMV0gPSAtMTtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gKDIgKiBmYXIgKiBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQub3J0aG8gPSBmdW5jdGlvbiAob3V0LCBsZWZ0LCByaWdodCwgYm90dG9tLCB0b3AsIG5lYXIsIGZhcikge1xuICAgIHZhciBsciA9IDEgLyAobGVmdCAtIHJpZ2h0KSxcbiAgICAgICAgYnQgPSAxIC8gKGJvdHRvbSAtIHRvcCksXG4gICAgICAgIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgICBvdXRbMF0gPSAtMiAqIGxyO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IDA7XG4gICAgb3V0WzVdID0gLTIgKiBidDtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gMDtcbiAgICBvdXRbOV0gPSAwO1xuICAgIG91dFsxMF0gPSAyICogbmY7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IChsZWZ0ICsgcmlnaHQpICogbHI7XG4gICAgb3V0WzEzXSA9ICh0b3AgKyBib3R0b20pICogYnQ7XG4gICAgb3V0WzE0XSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHt2ZWMzfSBleWUgUG9zaXRpb24gb2YgdGhlIHZpZXdlclxuICogQHBhcmFtIHt2ZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge3ZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5sb29rQXQgPSBmdW5jdGlvbiAob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgICB2YXIgeDAsIHgxLCB4MiwgeTAsIHkxLCB5MiwgejAsIHoxLCB6MiwgbGVuLFxuICAgICAgICBleWV4ID0gZXllWzBdLFxuICAgICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgICBleWV6ID0gZXllWzJdLFxuICAgICAgICB1cHggPSB1cFswXSxcbiAgICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICAgIHVweiA9IHVwWzJdLFxuICAgICAgICBjZW50ZXJ4ID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJ5ID0gY2VudGVyWzFdLFxuICAgICAgICBjZW50ZXJ6ID0gY2VudGVyWzJdO1xuXG4gICAgaWYgKE1hdGguYWJzKGV5ZXggLSBjZW50ZXJ4KSA8IEdMTUFUX0VQU0lMT04gJiZcbiAgICAgICAgTWF0aC5hYnMoZXlleSAtIGNlbnRlcnkpIDwgR0xNQVRfRVBTSUxPTiAmJlxuICAgICAgICBNYXRoLmFicyhleWV6IC0gY2VudGVyeikgPCBHTE1BVF9FUFNJTE9OKSB7XG4gICAgICAgIHJldHVybiBtYXQ0LmlkZW50aXR5KG91dCk7XG4gICAgfVxuXG4gICAgejAgPSBleWV4IC0gY2VudGVyeDtcbiAgICB6MSA9IGV5ZXkgLSBjZW50ZXJ5O1xuICAgIHoyID0gZXlleiAtIGNlbnRlcno7XG5cbiAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KHowICogejAgKyB6MSAqIHoxICsgejIgKiB6Mik7XG4gICAgejAgKj0gbGVuO1xuICAgIHoxICo9IGxlbjtcbiAgICB6MiAqPSBsZW47XG5cbiAgICB4MCA9IHVweSAqIHoyIC0gdXB6ICogejE7XG4gICAgeDEgPSB1cHogKiB6MCAtIHVweCAqIHoyO1xuICAgIHgyID0gdXB4ICogejEgLSB1cHkgKiB6MDtcbiAgICBsZW4gPSBNYXRoLnNxcnQoeDAgKiB4MCArIHgxICogeDEgKyB4MiAqIHgyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB4MCA9IDA7XG4gICAgICAgIHgxID0gMDtcbiAgICAgICAgeDIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHgwICo9IGxlbjtcbiAgICAgICAgeDEgKj0gbGVuO1xuICAgICAgICB4MiAqPSBsZW47XG4gICAgfVxuXG4gICAgeTAgPSB6MSAqIHgyIC0gejIgKiB4MTtcbiAgICB5MSA9IHoyICogeDAgLSB6MCAqIHgyO1xuICAgIHkyID0gejAgKiB4MSAtIHoxICogeDA7XG5cbiAgICBsZW4gPSBNYXRoLnNxcnQoeTAgKiB5MCArIHkxICogeTEgKyB5MiAqIHkyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB5MCA9IDA7XG4gICAgICAgIHkxID0gMDtcbiAgICAgICAgeTIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHkwICo9IGxlbjtcbiAgICAgICAgeTEgKj0gbGVuO1xuICAgICAgICB5MiAqPSBsZW47XG4gICAgfVxuXG4gICAgb3V0WzBdID0geDA7XG4gICAgb3V0WzFdID0geTA7XG4gICAgb3V0WzJdID0gejA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSB4MTtcbiAgICBvdXRbNV0gPSB5MTtcbiAgICBvdXRbNl0gPSB6MTtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IHgyO1xuICAgIG91dFs5XSA9IHkyO1xuICAgIG91dFsxMF0gPSB6MjtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gLSh4MCAqIGV5ZXggKyB4MSAqIGV5ZXkgKyB4MiAqIGV5ZXopO1xuICAgIG91dFsxM10gPSAtKHkwICogZXlleCArIHkxICogZXlleSArIHkyICogZXlleik7XG4gICAgb3V0WzE0XSA9IC0oejAgKiBleWV4ICsgejEgKiBleWV5ICsgejIgKiBleWV6KTtcbiAgICBvdXRbMTVdID0gMTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0NC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0NCgnICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgYVs2XSArICcsICcgKyBhWzddICsgJywgJyArXG4gICAgICAgICAgICAgICAgICAgIGFbOF0gKyAnLCAnICsgYVs5XSArICcsICcgKyBhWzEwXSArICcsICcgKyBhWzExXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVsxMl0gKyAnLCAnICsgYVsxM10gKyAnLCAnICsgYVsxNF0gKyAnLCAnICsgYVsxNV0gKyAnKSc7XG59O1xuXG4vKipcbiAqIFJldHVybnMgRnJvYmVuaXVzIG5vcm0gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gY2FsY3VsYXRlIEZyb2Jlbml1cyBub3JtIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBGcm9iZW5pdXMgbm9ybVxuICovXG5tYXQ0LmZyb2IgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgTWF0aC5wb3coYVs2XSwgMikgKyBNYXRoLnBvdyhhWzZdLCAyKSArIE1hdGgucG93KGFbN10sIDIpICsgTWF0aC5wb3coYVs4XSwgMikgKyBNYXRoLnBvdyhhWzldLCAyKSArIE1hdGgucG93KGFbMTBdLCAyKSArIE1hdGgucG93KGFbMTFdLCAyKSArIE1hdGgucG93KGFbMTJdLCAyKSArIE1hdGgucG93KGFbMTNdLCAyKSArIE1hdGgucG93KGFbMTRdLCAyKSArIE1hdGgucG93KGFbMTVdLCAyKSApKVxufTtcblxuXG5pZih0eXBlb2YoZXhwb3J0cykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZXhwb3J0cy5tYXQ0ID0gbWF0NDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIFF1YXRlcm5pb25cbiAqIEBuYW1lIHF1YXRcbiAqL1xuXG52YXIgcXVhdCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgcXVhdFxuICpcbiAqIEByZXR1cm5zIHtxdWF0fSBhIG5ldyBxdWF0ZXJuaW9uXG4gKi9cbnF1YXQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2V0cyBhIHF1YXRlcm5pb24gdG8gcmVwcmVzZW50IHRoZSBzaG9ydGVzdCByb3RhdGlvbiBmcm9tIG9uZVxuICogdmVjdG9yIHRvIGFub3RoZXIuXG4gKlxuICogQm90aCB2ZWN0b3JzIGFyZSBhc3N1bWVkIHRvIGJlIHVuaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgaW5pdGlhbCB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgZGVzdGluYXRpb24gdmVjdG9yXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQucm90YXRpb25UbyA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdG1wdmVjMyA9IHZlYzMuY3JlYXRlKCk7XG4gICAgdmFyIHhVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygxLDAsMCk7XG4gICAgdmFyIHlVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygwLDEsMCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgICAgIHZhciBkb3QgPSB2ZWMzLmRvdChhLCBiKTtcbiAgICAgICAgaWYgKGRvdCA8IC0wLjk5OTk5OSkge1xuICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB4VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgaWYgKHZlYzMubGVuZ3RoKHRtcHZlYzMpIDwgMC4wMDAwMDEpXG4gICAgICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB5VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgdmVjMy5ub3JtYWxpemUodG1wdmVjMywgdG1wdmVjMyk7XG4gICAgICAgICAgICBxdWF0LnNldEF4aXNBbmdsZShvdXQsIHRtcHZlYzMsIE1hdGguUEkpO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSBlbHNlIGlmIChkb3QgPiAwLjk5OTk5OSkge1xuICAgICAgICAgICAgb3V0WzBdID0gMDtcbiAgICAgICAgICAgIG91dFsxXSA9IDA7XG4gICAgICAgICAgICBvdXRbMl0gPSAwO1xuICAgICAgICAgICAgb3V0WzNdID0gMTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2ZWMzLmNyb3NzKHRtcHZlYzMsIGEsIGIpO1xuICAgICAgICAgICAgb3V0WzBdID0gdG1wdmVjM1swXTtcbiAgICAgICAgICAgIG91dFsxXSA9IHRtcHZlYzNbMV07XG4gICAgICAgICAgICBvdXRbMl0gPSB0bXB2ZWMzWzJdO1xuICAgICAgICAgICAgb3V0WzNdID0gMSArIGRvdDtcbiAgICAgICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBzcGVjaWZpZWQgcXVhdGVybmlvbiB3aXRoIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlblxuICogYXhlcy4gRWFjaCBheGlzIGlzIGEgdmVjMyBhbmQgaXMgZXhwZWN0ZWQgdG8gYmUgdW5pdCBsZW5ndGggYW5kXG4gKiBwZXJwZW5kaWN1bGFyIHRvIGFsbCBvdGhlciBzcGVjaWZpZWQgYXhlcy5cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZpZXcgIHRoZSB2ZWN0b3IgcmVwcmVzZW50aW5nIHRoZSB2aWV3aW5nIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSByaWdodCB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJyaWdodFwiIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSB1cCAgICB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJ1cFwiIGRpcmVjdGlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnNldEF4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hdHIgPSBtYXQzLmNyZWF0ZSgpO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgdmlldywgcmlnaHQsIHVwKSB7XG4gICAgICAgIG1hdHJbMF0gPSByaWdodFswXTtcbiAgICAgICAgbWF0clszXSA9IHJpZ2h0WzFdO1xuICAgICAgICBtYXRyWzZdID0gcmlnaHRbMl07XG5cbiAgICAgICAgbWF0clsxXSA9IHVwWzBdO1xuICAgICAgICBtYXRyWzRdID0gdXBbMV07XG4gICAgICAgIG1hdHJbN10gPSB1cFsyXTtcblxuICAgICAgICBtYXRyWzJdID0gLXZpZXdbMF07XG4gICAgICAgIG1hdHJbNV0gPSAtdmlld1sxXTtcbiAgICAgICAgbWF0cls4XSA9IC12aWV3WzJdO1xuXG4gICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIHF1YXQuZnJvbU1hdDMob3V0LCBtYXRyKSk7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBxdWF0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7cXVhdH0gYSBuZXcgcXVhdGVybmlvblxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY2xvbmUgPSB2ZWM0LmNsb25lO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3F1YXR9IGEgbmV3IHF1YXRlcm5pb25cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmZyb21WYWx1ZXMgPSB2ZWM0LmZyb21WYWx1ZXM7XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHF1YXQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBzb3VyY2UgcXVhdGVybmlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY29weSA9IHZlYzQuY29weTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSBxdWF0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB3IFcgY29tcG9uZW50XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zZXQgPSB2ZWM0LnNldDtcblxuLyoqXG4gKiBTZXQgYSBxdWF0IHRvIHRoZSBpZGVudGl0eSBxdWF0ZXJuaW9uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaWRlbnRpdHkgPSBmdW5jdGlvbihvdXQpIHtcbiAgICBvdXRbMF0gPSAwO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldHMgYSBxdWF0IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFuZCByb3RhdGlvbiBheGlzLFxuICogdGhlbiByZXR1cm5zIGl0LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIGFyb3VuZCB3aGljaCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqKi9cbnF1YXQuc2V0QXhpc0FuZ2xlID0gZnVuY3Rpb24ob3V0LCBheGlzLCByYWQpIHtcbiAgICByYWQgPSByYWQgKiAwLjU7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICAgIG91dFswXSA9IHMgKiBheGlzWzBdO1xuICAgIG91dFsxXSA9IHMgKiBheGlzWzFdO1xuICAgIG91dFsyXSA9IHMgKiBheGlzWzJdO1xuICAgIG91dFszXSA9IE1hdGguY29zKHJhZCk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmFkZCA9IHZlYzQuYWRkO1xuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICB2YXIgYXggPSBhWzBdLCBheSA9IGFbMV0sIGF6ID0gYVsyXSwgYXcgPSBhWzNdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdLCBidyA9IGJbM107XG5cbiAgICBvdXRbMF0gPSBheCAqIGJ3ICsgYXcgKiBieCArIGF5ICogYnogLSBheiAqIGJ5O1xuICAgIG91dFsxXSA9IGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieDtcbiAgICBvdXRbM10gPSBhdyAqIGJ3IC0gYXggKiBieCAtIGF5ICogYnkgLSBheiAqIGJ6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5tdWx0aXBseX1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0Lm11bCA9IHF1YXQubXVsdGlwbHk7XG5cbi8qKlxuICogU2NhbGVzIGEgcXVhdCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zY2FsZSA9IHZlYzQuc2NhbGU7XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVggPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ4ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYng7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF6ICogYng7XG4gICAgb3V0WzJdID0gYXogKiBidyAtIGF5ICogYng7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ5ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF3ICogYnk7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF4ICogYnk7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF5ICogYnk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBaIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVogPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ6ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF5ICogYno7XG4gICAgb3V0WzFdID0gYXkgKiBidyAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYno7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF6ICogYno7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgVyBjb21wb25lbnQgb2YgYSBxdWF0IGZyb20gdGhlIFgsIFksIGFuZCBaIGNvbXBvbmVudHMuXG4gKiBBc3N1bWVzIHRoYXQgcXVhdGVybmlvbiBpcyAxIHVuaXQgaW4gbGVuZ3RoLlxuICogQW55IGV4aXN0aW5nIFcgY29tcG9uZW50IHdpbGwgYmUgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBXIGNvbXBvbmVudCBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LmNhbGN1bGF0ZVcgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG5cbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSAtTWF0aC5zcXJ0KE1hdGguYWJzKDEuMCAtIHggKiB4IC0geSAqIHkgLSB6ICogeikpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byBxdWF0J3NcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmRvdCA9IHZlYzQuZG90O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlcnAgPSB2ZWM0LmxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuc2xlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgLy8gYmVuY2htYXJrczpcbiAgICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIGF4ID0gYVswXSwgYXkgPSBhWzFdLCBheiA9IGFbMl0sIGF3ID0gYVszXSxcbiAgICAgICAgYnggPSBiWzBdLCBieSA9IGJbMV0sIGJ6ID0gYlsyXSwgYncgPSBiWzNdO1xuXG4gICAgdmFyICAgICAgICBvbWVnYSwgY29zb20sIHNpbm9tLCBzY2FsZTAsIHNjYWxlMTtcblxuICAgIC8vIGNhbGMgY29zaW5lXG4gICAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3O1xuICAgIC8vIGFkanVzdCBzaWducyAoaWYgbmVjZXNzYXJ5KVxuICAgIGlmICggY29zb20gPCAwLjAgKSB7XG4gICAgICAgIGNvc29tID0gLWNvc29tO1xuICAgICAgICBieCA9IC0gYng7XG4gICAgICAgIGJ5ID0gLSBieTtcbiAgICAgICAgYnogPSAtIGJ6O1xuICAgICAgICBidyA9IC0gYnc7XG4gICAgfVxuICAgIC8vIGNhbGN1bGF0ZSBjb2VmZmljaWVudHNcbiAgICBpZiAoICgxLjAgLSBjb3NvbSkgPiAwLjAwMDAwMSApIHtcbiAgICAgICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgICAgIG9tZWdhICA9IE1hdGguYWNvcyhjb3NvbSk7XG4gICAgICAgIHNpbm9tICA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgc2NhbGUwID0gTWF0aC5zaW4oKDEuMCAtIHQpICogb21lZ2EpIC8gc2lub207XG4gICAgICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbTtcbiAgICB9IGVsc2UgeyAgICAgICAgXG4gICAgICAgIC8vIFwiZnJvbVwiIGFuZCBcInRvXCIgcXVhdGVybmlvbnMgYXJlIHZlcnkgY2xvc2UgXG4gICAgICAgIC8vICAuLi4gc28gd2UgY2FuIGRvIGEgbGluZWFyIGludGVycG9sYXRpb25cbiAgICAgICAgc2NhbGUwID0gMS4wIC0gdDtcbiAgICAgICAgc2NhbGUxID0gdDtcbiAgICB9XG4gICAgLy8gY2FsY3VsYXRlIGZpbmFsIHZhbHVlc1xuICAgIG91dFswXSA9IHNjYWxlMCAqIGF4ICsgc2NhbGUxICogYng7XG4gICAgb3V0WzFdID0gc2NhbGUwICogYXkgKyBzY2FsZTEgKiBieTtcbiAgICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6O1xuICAgIG91dFszXSA9IHNjYWxlMCAqIGF3ICsgc2NhbGUxICogYnc7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgaW52ZXJzZSBvZiBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBpbnZlcnNlIG9mXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgZG90ID0gYTAqYTAgKyBhMSphMSArIGEyKmEyICsgYTMqYTMsXG4gICAgICAgIGludkRvdCA9IGRvdCA/IDEuMC9kb3QgOiAwO1xuICAgIFxuICAgIC8vIFRPRE86IFdvdWxkIGJlIGZhc3RlciB0byByZXR1cm4gWzAsMCwwLDBdIGltbWVkaWF0ZWx5IGlmIGRvdCA9PSAwXG5cbiAgICBvdXRbMF0gPSAtYTAqaW52RG90O1xuICAgIG91dFsxXSA9IC1hMSppbnZEb3Q7XG4gICAgb3V0WzJdID0gLWEyKmludkRvdDtcbiAgICBvdXRbM10gPSBhMyppbnZEb3Q7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY29uanVnYXRlIG9mIGEgcXVhdFxuICogSWYgdGhlIHF1YXRlcm5pb24gaXMgbm9ybWFsaXplZCwgdGhpcyBmdW5jdGlvbiBpcyBmYXN0ZXIgdGhhbiBxdWF0LmludmVyc2UgYW5kIHByb2R1Y2VzIHRoZSBzYW1lIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBjb25qdWdhdGUgb2ZcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xucXVhdC5jb25qdWdhdGUgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF07XG4gICAgb3V0WzFdID0gLWFbMV07XG4gICAgb3V0WzJdID0gLWFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubGVuZ3RoID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBxdWF0Lmxlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlbiA9IHF1YXQubGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zcXVhcmVkTGVuZ3RoID0gdmVjNC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5zcXVhcmVkTGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuc3FyTGVuID0gcXVhdC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubm9ybWFsaXplID0gdmVjNC5ub3JtYWxpemU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHF1YXRlcm5pb24gZnJvbSB0aGUgZ2l2ZW4gM3gzIHJvdGF0aW9uIG1hdHJpeC5cbiAqXG4gKiBOT1RFOiBUaGUgcmVzdWx0YW50IHF1YXRlcm5pb24gaXMgbm90IG5vcm1hbGl6ZWQsIHNvIHlvdSBzaG91bGQgYmUgc3VyZVxuICogdG8gcmVub3JtYWxpemUgdGhlIHF1YXRlcm5pb24geW91cnNlbGYgd2hlcmUgbmVjZXNzYXJ5LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHttYXQzfSBtIHJvdGF0aW9uIG1hdHJpeFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuZnJvbU1hdDMgPSBmdW5jdGlvbihvdXQsIG0pIHtcbiAgICAvLyBBbGdvcml0aG0gaW4gS2VuIFNob2VtYWtlJ3MgYXJ0aWNsZSBpbiAxOTg3IFNJR0dSQVBIIGNvdXJzZSBub3Rlc1xuICAgIC8vIGFydGljbGUgXCJRdWF0ZXJuaW9uIENhbGN1bHVzIGFuZCBGYXN0IEFuaW1hdGlvblwiLlxuICAgIHZhciBmVHJhY2UgPSBtWzBdICsgbVs0XSArIG1bOF07XG4gICAgdmFyIGZSb290O1xuXG4gICAgaWYgKCBmVHJhY2UgPiAwLjAgKSB7XG4gICAgICAgIC8vIHx3fCA+IDEvMiwgbWF5IGFzIHdlbGwgY2hvb3NlIHcgPiAxLzJcbiAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMS4wKTsgIC8vIDJ3XG4gICAgICAgIG91dFszXSA9IDAuNSAqIGZSb290O1xuICAgICAgICBmUm9vdCA9IDAuNS9mUm9vdDsgIC8vIDEvKDR3KVxuICAgICAgICBvdXRbMF0gPSAobVs3XS1tWzVdKSpmUm9vdDtcbiAgICAgICAgb3V0WzFdID0gKG1bMl0tbVs2XSkqZlJvb3Q7XG4gICAgICAgIG91dFsyXSA9IChtWzNdLW1bMV0pKmZSb290O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHx3fCA8PSAxLzJcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBpZiAoIG1bNF0gPiBtWzBdIClcbiAgICAgICAgICBpID0gMTtcbiAgICAgICAgaWYgKCBtWzhdID4gbVtpKjMraV0gKVxuICAgICAgICAgIGkgPSAyO1xuICAgICAgICB2YXIgaiA9IChpKzEpJTM7XG4gICAgICAgIHZhciBrID0gKGkrMiklMztcbiAgICAgICAgXG4gICAgICAgIGZSb290ID0gTWF0aC5zcXJ0KG1baSozK2ldLW1baiozK2pdLW1bayozK2tdICsgMS4wKTtcbiAgICAgICAgb3V0W2ldID0gMC41ICogZlJvb3Q7XG4gICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7XG4gICAgICAgIG91dFszXSA9IChtW2sqMytqXSAtIG1baiozK2tdKSAqIGZSb290O1xuICAgICAgICBvdXRbal0gPSAobVtqKjMraV0gKyBtW2kqMytqXSkgKiBmUm9vdDtcbiAgICAgICAgb3V0W2tdID0gKG1bayozK2ldICsgbVtpKjMra10pICogZlJvb3Q7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBxdWF0ZW5pb25cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG5xdWF0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdxdWF0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMucXVhdCA9IHF1YXQ7XG59XG47XG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbiAgfSkoc2hpbS5leHBvcnRzKTtcbn0pKHRoaXMpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBjb25zdGFudCh2YWx1ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVOdW1iZXIoYSwgYiwgdCkge1xuICAgIHJldHVybiAoYSAqICgxIC0gdCkpICsgKGIgKiB0KTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVBcnJheShhLCBiLCB0KSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBpbnRlcnBvbGF0ZU51bWJlcihhW2ldLCBiW2ldLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0c1snaW50ZXJwb2xhdGVkJ10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzLFxuICAgICAgICBiYXNlID0gZi5iYXNlIHx8IDEsXG4gICAgICAgIGludGVycG9sYXRlID0gQXJyYXkuaXNBcnJheShzdG9wc1swXVsxXSkgPyBpbnRlcnBvbGF0ZUFycmF5IDogaW50ZXJwb2xhdGVOdW1iZXI7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oeikge1xuICAgICAgICAvLyBmaW5kIHRoZSB0d28gc3RvcHMgd2hpY2ggdGhlIGN1cnJlbnQgeiBpcyBiZXR3ZWVuXG4gICAgICAgIHZhciBsb3csIGhpZ2g7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0b3AgPSBzdG9wc1tpXTtcblxuICAgICAgICAgICAgaWYgKHN0b3BbMF0gPD0geikge1xuICAgICAgICAgICAgICAgIGxvdyA9IHN0b3A7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdG9wWzBdID4geikge1xuICAgICAgICAgICAgICAgIGhpZ2ggPSBzdG9wO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxvdyAmJiBoaWdoKSB7XG4gICAgICAgICAgICB2YXIgem9vbURpZmYgPSBoaWdoWzBdIC0gbG93WzBdLFxuICAgICAgICAgICAgICAgIHpvb21Qcm9ncmVzcyA9IHogLSBsb3dbMF0sXG5cbiAgICAgICAgICAgICAgICB0ID0gYmFzZSA9PT0gMSA/XG4gICAgICAgICAgICAgICAgem9vbVByb2dyZXNzIC8gem9vbURpZmYgOlxuICAgICAgICAgICAgICAgIChNYXRoLnBvdyhiYXNlLCB6b29tUHJvZ3Jlc3MpIC0gMSkgLyAoTWF0aC5wb3coYmFzZSwgem9vbURpZmYpIC0gMSk7XG5cbiAgICAgICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZShsb3dbMV0sIGhpZ2hbMV0sIHQpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobG93KSB7XG4gICAgICAgICAgICByZXR1cm4gbG93WzFdO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoaGlnaCkge1xuICAgICAgICAgICAgcmV0dXJuIGhpZ2hbMV07XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuZXhwb3J0c1sncGllY2V3aXNlLWNvbnN0YW50J10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHopIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHN0b3BzW2ldWzBdID4geikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9wc1tpID09PSAwID8gMCA6IGkgLSAxXVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdG9wc1tzdG9wcy5sZW5ndGggLSAxXVsxXTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi4vLi4vcmVmZXJlbmNlL2xhdGVzdC5qcycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9wYXJzZWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHlsZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZShzdHlsZSwgcmVmZXJlbmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xudmFyIGZvcm1hdCA9IHJlcXVpcmUoJ3V0aWwnKS5mb3JtYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3R5bGUsIHJlZmVyZW5jZSkge1xuXG4gICAgdmFyIGNvbnN0YW50cyA9IHN0eWxlLmNvbnN0YW50cyB8fCB7fSxcbiAgICAgICAgbGF5ZXJzID0ge30sXG4gICAgICAgIGVycm9ycyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZXJyb3Ioa2V5LCB2YWwgLyosIG1lc3NhZ2UsIC4uLiovKSB7XG4gICAgICAgIHZhciBlcnIgPSB7XG4gICAgICAgICAgICBtZXNzYWdlOiAoa2V5ID8ga2V5ICsgJzogJyA6ICcnKSArXG4gICAgICAgICAgICBmb3JtYXQuYXBwbHkoZm9ybWF0LCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsLl9fbGluZV9fKSB7XG4gICAgICAgICAgICBlcnIubGluZSA9IHZhbC5fX2xpbmVfXztcbiAgICAgICAgfVxuXG4gICAgICAgIGVycm9ycy5wdXNoKGVycik7XG4gICAgfVxuXG4gICAgLy8gTWFpbiByZWN1cnNpdmUgdmFsaWRhdGlvbiBmdW5jdGlvbi4gVHJhY2tzOlxuICAgIC8vXG4gICAgLy8gLSBrZXk6IHN0cmluZyByZXByZXNlbnRpbmcgbG9jYXRpb24gb2YgdmFsaWRhdGlvbiBpbiBzdHlsZSB0cmVlLiBVc2VkIG9ubHlcbiAgICAvLyAgIGZvciBtb3JlIGluZm9ybWF0aXZlIGVycm9yIHJlcG9ydGluZy5cbiAgICAvLyAtIHZhbDogY3VycmVudCB2YWx1ZSBmcm9tIHN0eWxlIGJlaW5nIGV2YWx1YXRlZC4gTWF5IGJlIGFueXRoaW5nIGZyb20gYVxuICAgIC8vICAgaGlnaCBsZXZlbCBvYmplY3QgdGhhdCBuZWVkcyB0byBiZSBkZXNjZW5kZWQgaW50byBkZWVwZXIgb3IgYSBzaW1wbGVcbiAgICAvLyAgIHNjYWxhciB2YWx1ZS5cbiAgICAvLyAtIHNwZWM6IGN1cnJlbnQgc3BlYyBiZWluZyBldmFsdWF0ZWQuIFRyYWNrcyB2YWwuXG4gICAgLy9cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcblxuICAgICAgICAvLyBDb25zdGFudHNcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIHZhbFswXSA9PT0gJ0AnKSB7XG4gICAgICAgICAgICBpZiAoISh2YWwgaW4gY29uc3RhbnRzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2NvbnN0YW50IFwiJXNcIiBub3QgZm91bmQnLCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsID0gY29uc3RhbnRzW3ZhbF07XG4gICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRnVuY3Rpb25zXG4gICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uICYmIHR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRhdGUuZnVuY3Rpb24oa2V5LCB2YWwsIHNwZWMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNwZWMudHlwZSkge1xuICAgICAgICAgICAgdmFyIHZhbGlkYXRvciA9IHZhbGlkYXRlW3NwZWMudHlwZV07XG4gICAgICAgICAgICBpZiAodmFsaWRhdG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbGlkYXRvcihrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzcGVjID0gcmVmZXJlbmNlW3NwZWMudHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHNwZWMpO1xuICAgIH1cblxuICAgIHZhbGlkYXRlLmNvbnN0YW50cyA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICBpZiAodHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ29iamVjdCBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGsgaW4gdmFsKSB7XG4gICAgICAgICAgICBpZiAoa1swXSAhPT0gJ0AnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJy4nICsgaywgdmFsW2tdLCAnY29uc3RhbnRzIG11c3Qgc3RhcnQgd2l0aCBcIkBcIicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLnNvdXJjZSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnXCJ0eXBlXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgICAgICBjYXNlICdyYXN0ZXInOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV90aWxlKTtcblxuICAgICAgICAgICAgICAgIGlmICgndXJsJyBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChbJ3R5cGUnLCAndXJsJywgJ3RpbGVTaXplJ10uaW5kZXhPZihwcm9wKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXkgKyAnLicgKyBwcm9wLCB2YWxbcHJvcF0sICdhIHNvdXJjZSB3aXRoIGEgXCJ1cmxcIiBwcm9wZXJ0eSBtYXkgbm90IGluY2x1ZGUgYSBcIiVzXCIgcHJvcGVydHknLCBwcm9wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZ2VvanNvbic6XG4gICAgICAgICAgICAgICAgdmFsaWRhdGUub2JqZWN0KGtleSwgdmFsLCByZWZlcmVuY2Uuc291cmNlX2dlb2pzb24pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndmlkZW8nOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV92aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJy50eXBlJywgdmFsLnR5cGUsIHt2YWx1ZXM6IFsndmVjdG9yJywgJ3Jhc3RlcicsICdnZW9qc29uJywgJ3ZpZGVvJ119KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YWxpZGF0ZS5sYXllciA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUgJiYgIXZhbC5yZWYpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnZWl0aGVyIFwidHlwZVwiIG9yIFwicmVmXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpLFxuICAgICAgICAgICAgcmVmID0gdW5idW5kbGUodmFsLnJlZik7XG5cbiAgICAgICAgaWYgKHZhbC5pZCkge1xuICAgICAgICAgICAgaWYgKGxheWVyc1t2YWwuaWRdKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwuaWQsICdkdXBsaWNhdGUgbGF5ZXIgaWQgXCIlc1wiLCBwcmV2aW91c2x5IHVzZWQgYXQgbGluZSAlZCcsIHZhbC5pZCwgbGF5ZXJzW3ZhbC5pZF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsYXllcnNbdmFsLmlkXSA9IHZhbC5pZC5fX2xpbmVfXztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgncmVmJyBpbiB2YWwpIHtcbiAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJywgJ2ZpbHRlcicsICdsYXlvdXQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHAgaW4gdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsW3BdLCAnXCIlc1wiIGlzIHByb2hpYml0ZWQgZm9yIHJlZiBsYXllcnMnLCBwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHBhcmVudDtcblxuICAgICAgICAgICAgc3R5bGUubGF5ZXJzLmZvckVhY2goZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAobGF5ZXIuaWQgPT0gcmVmKSBwYXJlbnQgPSBsYXllcjtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBsYXllciBcIiVzXCIgbm90IGZvdW5kJywgcmVmKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50LnJlZikge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBjYW5ub3QgcmVmZXJlbmNlIGFub3RoZXIgcmVmIGxheWVyJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJlbnQudHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlICE9PSAnYmFja2dyb3VuZCcpIHtcbiAgICAgICAgICAgIGlmICghdmFsLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcInNvdXJjZVwiJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzb3VyY2UgPSBzdHlsZS5zb3VyY2VzW3ZhbC5zb3VyY2VdO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ3NvdXJjZSBcIiVzXCIgbm90IGZvdW5kJywgdmFsLnNvdXJjZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzb3VyY2UudHlwZSA9PSAndmVjdG9yJyAmJiB0eXBlID09ICdyYXN0ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ2xheWVyIFwiJXNcIiByZXF1aXJlcyBhIHJhc3RlciBzb3VyY2UnLCB2YWwuaWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc291cmNlLnR5cGUgPT0gJ3Jhc3RlcicgJiYgdHlwZSAhPSAncmFzdGVyJykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbC5zb3VyY2UsICdsYXllciBcIiVzXCIgcmVxdWlyZXMgYSB2ZWN0b3Igc291cmNlJywgdmFsLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5sYXllciwge1xuICAgICAgICAgICAgZmlsdGVyOiB2YWxpZGF0ZS5maWx0ZXIsXG4gICAgICAgICAgICBsYXlvdXQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ2xheW91dF8nICsgdHlwZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGUgJiYgc3BlYyAmJiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFpbnQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ3BhaW50XycgKyB0eXBlXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZSAmJiBzcGVjICYmIHZhbGlkYXRlKGtleSwgdmFsLCBzcGVjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLm9iamVjdCA9IGZ1bmN0aW9uIChrZXksIHZhbCwgc3BlYywgdmFsaWRhdG9ycykge1xuICAgICAgICB2YWxpZGF0b3JzID0gdmFsaWRhdG9ycyB8fCB7fTtcblxuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdvYmplY3QgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBrIGluIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNwZWNrZXkgPSBrLnNwbGl0KCcuJylbMF07IC8vIHRyZWF0ICdwYWludC4qJyBhcyAncGFpbnQnXG4gICAgICAgICAgICB2YXIgZGVmID0gc3BlY1tzcGVja2V5XSB8fCBzcGVjWycqJ107XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHNwZWNrZXkubWF0Y2goL14oLiopLXRyYW5zaXRpb24kLyk7XG5cbiAgICAgICAgICAgIGlmIChkZWYpIHtcbiAgICAgICAgICAgICAgICAodmFsaWRhdG9yc1tzcGVja2V5XSB8fCB2YWxpZGF0ZSkoKGtleSA/IGtleSArICcuJyA6IGtleSkgKyBrLCB2YWxba10sIGRlZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zaXRpb24gJiYgc3BlY1t0cmFuc2l0aW9uWzFdXSAmJiBzcGVjW3RyYW5zaXRpb25bMV1dLnRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZSgoa2V5ID8ga2V5ICsgJy4nIDoga2V5KSArIGssIHZhbFtrXSwgcmVmZXJlbmNlLnRyYW5zaXRpb24pO1xuICAgICAgICAgICAgLy8gdG9sZXJhdGUgcm9vdC1sZXZlbCBleHRyYSBrZXlzICYgYXJiaXRyYXJ5IGxheWVyIHByb3BlcnRpZXNcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ICE9PSAnJyAmJiBrZXkuc3BsaXQoJy4nKS5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbFtrXSwgJ3Vua25vd24gcHJvcGVydHkgXCIlc1wiJywgayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBsIGluIHNwZWMpIHtcbiAgICAgICAgICAgIGlmIChzcGVjW2xdLnJlcXVpcmVkICYmIHNwZWNbbF1bJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIHZhbFtsXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwiJXNcIicsIGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmFycmF5ID0gZnVuY3Rpb24gKGtleSwgdmFsLCBzcGVjLCB2YWxpZGF0b3IpIHtcbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzcGVjLmxlbmd0aCAmJiB2YWwubGVuZ3RoICE9PSBzcGVjLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgbGVuZ3RoICVkIGV4cGVjdGVkLCBsZW5ndGggJWQgZm91bmQnLCBzcGVjLmxlbmd0aCwgdmFsLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdmFsdWUgPSB7XG4gICAgICAgICAgICBcInR5cGVcIjogc3BlYy52YWx1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzdHlsZS52ZXJzaW9uIDwgNykge1xuICAgICAgICAgICAgdmFsdWUuZnVuY3Rpb24gPSBzcGVjLmZ1bmN0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZl8oc3BlYy52YWx1ZSkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHNwZWMudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgKHZhbGlkYXRvciB8fCB2YWxpZGF0ZSkoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZmlsdGVyID0gZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICAgICAgdmFyIHR5cGU7XG5cbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwubGVuZ3RoIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnZmlsdGVyIGFycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCAxIGVsZW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1swXScsIHZhbFswXSwgcmVmZXJlbmNlLmZpbHRlcl9vcGVyYXRvcik7XG5cbiAgICAgICAgc3dpdGNoICh1bmJ1bmRsZSh2YWxbMF0pKSB7XG4gICAgICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID49IDIgJiYgdmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdcIiR0eXBlXCIgY2Fubm90IGJlIHVzZSB3aXRoIG9wZXJhdG9yIFwiJXNcIicsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnPT0nOlxuICAgICAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoICE9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdmaWx0ZXIgYXJyYXkgZm9yIG9wZXJhdG9yIFwiJXNcIiBtdXN0IGhhdmUgMyBlbGVtZW50cycsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnaW4nOlxuICAgICAgICAgICAgY2FzZSAnIWluJzpcbiAgICAgICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSB0eXBlb2ZfKHZhbFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ3N0cmluZyBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWxbMV1bMF0gPT09ICdAJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ2ZpbHRlciBrZXkgY2Fubm90IGJlIGEgY29uc3RhbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWxbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCByZWZlcmVuY2UuZ2VvbWV0cnlfdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgdmFsW2ldWzBdID09PSAnQCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbJyArIGkgKyAnXScsIHZhbFtpXSwgJ2ZpbHRlciB2YWx1ZSBjYW5ub3QgYmUgYSBjb25zdGFudCcpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgIT09ICdzdHJpbmcnICYmIHR5cGUgIT09ICdudW1iZXInICYmIHR5cGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCAnc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4gZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2FueSc6XG4gICAgICAgICAgICBjYXNlICdhbGwnOlxuICAgICAgICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZS5maWx0ZXIoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZnVuY3Rpb24gPSBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5mdW5jdGlvbiwge1xuICAgICAgICAgICAgc3RvcHM6IGZ1bmN0aW9uIChrZXksIHZhbCwgYXJyYXlTcGVjKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RTdG9wID0gLUluZmluaXR5O1xuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmFycmF5KGtleSwgdmFsLCBhcnJheVNwZWMsIGZ1bmN0aW9uIHZhbGlkYXRlU3RvcChrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mXyh2YWwpICE9PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdhcnJheSBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlb2ZfKHZhbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2FycmF5IGxlbmd0aCAlZCBleHBlY3RlZCwgbGVuZ3RoICVkIGZvdW5kJywgMiwgdmFsLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZShrZXkgKyAnWzBdJywgdmFsWzBdLCB7dHlwZTogJ251bWJlcid9KTtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGUoa2V5ICsgJ1sxXScsIHZhbFsxXSwgc3BlYyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZl8odmFsWzBdKSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uID09PSAncGllY2V3aXNlLWNvbnN0YW50JyAmJiB2YWxbMF0gJSAxICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1swXScsIHZhbFswXSwgJ3pvb20gbGV2ZWwgZm9yIHBpZWNld2lzZS1jb25zdGFudCBmdW5jdGlvbnMgbXVzdCBiZSBhbiBpbnRlZ2VyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxbMF0gPCBsYXN0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbMF0nLCB2YWxbMF0sICdhcnJheSBzdG9wcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFN0b3AgPSB2YWxbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2ZfKHZhbCkgPT09ICdhcnJheScgJiYgdmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2FycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgc3RvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmVudW0gPSBmdW5jdGlvbiAoa2V5LCB2YWwsIHNwZWMpIHtcbiAgICAgICAgaWYgKHNwZWMudmFsdWVzLmluZGV4T2YodW5idW5kbGUodmFsKSkgPT09IC0xKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2V4cGVjdGVkIG9uZSBvZiBbJXNdLCAlcyBmb3VuZCcsIHNwZWMudmFsdWVzLmpvaW4oJywgJyksIHZhbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuY29sb3IgPSBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2NvbG9yIGV4cGVjdGVkLCAlcyBmb3VuZCcsIHR5cGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcnNlQ1NTQ29sb3IodmFsKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdjb2xvciBleHBlY3RlZCwgXCIlc1wiIGZvdW5kJywgdmFsKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB0eXBlVmFsaWRhdG9yKGV4cGVjdGVkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICAgICAgdmFyIGFjdHVhbCA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgICAgIGlmIChhY3R1YWwgIT09IGV4cGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBleHBlY3RlZCwgJXMgZm91bmQnLCBleHBlY3RlZCwgYWN0dWFsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCdtaW5pbXVtJyBpbiBzcGVjICYmIHZhbCA8IHNwZWMubWluaW11bSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnJXMgaXMgbGVzcyB0aGFuIHRoZSBtaW5pbXVtIHZhbHVlICVzJywgdmFsLCBzcGVjLm1pbmltdW0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJ21heGltdW0nIGluIHNwZWMgJiYgdmFsID4gc3BlYy5tYXhpbXVtKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gdmFsdWUgJXMnLCB2YWwsIHNwZWMubWF4aW11bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFsaWRhdGUubnVtYmVyID0gdHlwZVZhbGlkYXRvcignbnVtYmVyJyk7XG4gICAgdmFsaWRhdGUuc3RyaW5nID0gdHlwZVZhbGlkYXRvcignc3RyaW5nJyk7XG4gICAgdmFsaWRhdGUuYm9vbGVhbiA9IHR5cGVWYWxpZGF0b3IoJ2Jvb2xlYW4nKTtcblxuICAgIHZhbGlkYXRlWycqJ10gPSBmdW5jdGlvbigpIHt9O1xuXG4gICAgdmFsaWRhdGUoJycsIHN0eWxlLCByZWZlcmVuY2UuJHJvb3QpO1xuXG4gICAgcmV0dXJuIGVycm9ycztcbn07XG5cbmZ1bmN0aW9uIHR5cGVvZl8odmFsKSB7XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE51bWJlcilcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBTdHJpbmcpXG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBpZiAodmFsIGluc3RhbmNlb2YgQm9vbGVhbilcbiAgICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICByZXR1cm4gJ2FycmF5JztcbiAgICBpZiAodmFsID09PSBudWxsKVxuICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgIHJldHVybiB0eXBlb2YgdmFsO1xufVxuXG5mdW5jdGlvbiB1bmJ1bmRsZShfKSB7XG4gICAgaWYgKF8gaW5zdGFuY2VvZiBOdW1iZXIgfHxcbiAgICAgICAgXyBpbnN0YW5jZW9mIFN0cmluZyB8fFxuICAgICAgICBfIGluc3RhbmNlb2YgQm9vbGVhbikge1xuICAgICAgICByZXR1cm4gXy52YWx1ZU9mKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIF87XG4gICAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3Y3Lmpzb24nKTtcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkdmVyc2lvblwiOiA3LFxuICBcIiRyb290XCI6IHtcbiAgICBcInZlcnNpb25cIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICA3XG4gICAgICBdLFxuICAgICAgXCJkb2NcIjogXCJTdHlsZXNoZWV0IHZlcnNpb24gbnVtYmVyLiBNdXN0IGJlIDcuXCJcbiAgICB9LFxuICAgIFwibmFtZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBodW1hbi1yZWFkYWJsZSBuYW1lIGZvciB0aGUgc3R5bGUuXCJcbiAgICB9LFxuICAgIFwiY29uc3RhbnRzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbnN0YW50c1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBvYmplY3Qgb2YgY29uc3RhbnRzIHRvIGJlIHJlZmVyZW5jZWQgaW4gbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZXNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwic291cmNlc1wiLFxuICAgICAgXCJkb2NcIjogXCJEYXRhIHNvdXJjZSBzcGVjaWZpY2F0aW9ucy5cIlxuICAgIH0sXG4gICAgXCJzcHJpdGVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgYmFzZSBVUkwgZm9yIHJldHJpZXZpbmcgdGhlIHNwcml0ZSBpbWFnZSBhbmQgbWV0YWRhdGEuIFRoZSBleHRlbnNpb25zIGAucG5nYCwgYC5qc29uYCBhbmQgc2NhbGUgZmFjdG9yIGBAMngucG5nYCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQuXCJcbiAgICB9LFxuICAgIFwiZ2x5cGhzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJBIFVSTCB0ZW1wbGF0ZSBmb3IgbG9hZGluZyBzaWduZWQtZGlzdGFuY2UtZmllbGQgZ2x5cGggc2V0cyBpbiBQQkYgZm9ybWF0LiBWYWxpZCB0b2tlbnMgYXJlIHtmb250c3RhY2t9IGFuZCB7cmFuZ2V9LlwiXG4gICAgfSxcbiAgICBcInRyYW5zaXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwidHJhbnNpdGlvblwiLFxuICAgICAgXCJkb2NcIjogXCJBIGdsb2JhbCB0cmFuc2l0aW9uIGRlZmluaXRpb24gdG8gdXNlIGFzIGEgZGVmYXVsdCBhY3Jvc3MgcHJvcGVydGllcy5cIlxuICAgIH0sXG4gICAgXCJsYXllcnNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJsYXllclwiLFxuICAgICAgXCJkb2NcIjogXCJMYXllcnMgd2lsbCBiZSBkcmF3biBpbiB0aGUgb3JkZXIgb2YgdGhpcyBhcnJheS5cIlxuICAgIH1cbiAgfSxcbiAgXCJjb25zdGFudHNcIjoge1xuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIkEgY29uc3RhbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkIHZlcmJhdGltIGluIHRoZSByZWZlcmVuY2luZyBwbGFjZS4gVGhpcyBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBvYmplY3RzIGFuZCBhcnJheXMuIEFsbCB2YXJpYWJsZSBuYW1lcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggYW4gYEBgIHN5bWJvbC5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VzXCI6IHtcbiAgICBcIipcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic291cmNlXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmljYXRpb24gb2YgYSBkYXRhIHNvdXJjZS4gRm9yIHZlY3RvciBhbmQgcmFzdGVyIHNvdXJjZXMsIGVpdGhlciBUaWxlSlNPTiBvciBhIFVSTCB0byBhIFRpbGVKU09OIG11c3QgYmUgcHJvdmlkZWQuIEZvciBHZW9KU09OIGFuZCB2aWRlbyBzb3VyY2VzLCBhIFVSTCBtdXN0IGJlIHByb3ZpZGVkLlwiXG4gICAgfVxuICB9LFxuICBcInNvdXJjZVwiOiBbXG4gICAgXCJzb3VyY2VfdGlsZVwiLFxuICAgIFwic291cmNlX2dlb2pzb25cIixcbiAgICBcInNvdXJjZV92aWRlb1wiXG4gIF0sXG4gIFwic291cmNlX3RpbGVcIjoge1xuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmVjdG9yXCIsXG4gICAgICAgIFwicmFzdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlRoZSBkYXRhIHR5cGUgb2YgdGhlIHNvdXJjZS5cIlxuICAgIH0sXG4gICAgXCJ1cmxcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgVVJMIHRvIGEgVGlsZUpTT04gcmVzb3VyY2UuIFN1cHBvcnRlZCBwcm90b2NvbHMgYXJlIGBodHRwOmAsIGBodHRwczpgLCBhbmQgYG1hcGJveDovLzxtYXBpZD5gLlwiXG4gICAgfSxcbiAgICBcInRpbGVzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkFuIGFycmF5IG9mIG9uZSBvciBtb3JlIHRpbGUgc291cmNlIFVSTHMsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSB6b29tIGxldmVsIGZvciB3aGljaCB0aWxlcyBhcmUgYXZhaWxhYmxlLCBhcyBpbiB0aGUgVGlsZUpTT04gc3BlYy5cIlxuICAgIH0sXG4gICAgXCJtYXh6b29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJNYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHdoaWNoIHRpbGVzIGFyZSBhdmFpbGFibGUsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLiBEYXRhIGZyb20gdGlsZXMgYXQgdGhlIG1heHpvb20gYXJlIHVzZWQgd2hlbiBkaXNwbGF5aW5nIHRoZSBtYXAgYXQgaGlnaGVyIHpvb20gbGV2ZWxzLlwiXG4gICAgfSxcbiAgICBcInRpbGVTaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDUxMixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gdmlzdWFsIHNpemUgdG8gZGlzcGxheSB0aWxlcyBmb3IgdGhpcyBsYXllci4gT25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBsYXllcnMuXCJcbiAgICB9LFxuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIk90aGVyIGtleXMgdG8gY29uZmlndXJlIHRoZSBkYXRhIHNvdXJjZS5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VfZ2VvanNvblwiOiB7XG4gICAgXCJ0eXBlXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJnZW9qc29uXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiZGF0YVwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCJcbiAgICB9XG4gIH0sXG4gIFwic291cmNlX3ZpZGVvXCI6IHtcbiAgICBcInR5cGVcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpZGVvXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidXJsXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIlVSTHMgdG8gdmlkZW8gY29udGVudCBpbiBvcmRlciBvZiBwcmVmZXJyZWQgZm9ybWF0LlwiXG4gICAgfSxcbiAgICBcImNvb3JkaW5hdGVzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcImxlbmd0aFwiOiA0LFxuICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIlxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgXCJsYXllclwiOiB7XG4gICAgXCJpZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiVW5pcXVlIGxheWVyIG5hbWUuXCJcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiZmlsbFwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJzeW1ib2xcIixcbiAgICAgICAgXCJyYXN0ZXJcIixcbiAgICAgICAgXCJiYWNrZ3JvdW5kXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlJlbmRlcmluZyB0eXBlIG9mIHRoaXMgbGF5ZXIuXCJcbiAgICB9LFxuICAgIFwicmVmXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJSZWZlcmVuY2VzIGFub3RoZXIgbGF5ZXIgdG8gY29weSBgdHlwZWAsIGBzb3VyY2VgLCBgc291cmNlLWxheWVyYCwgYG1pbnpvb21gLCBgbWF4em9vbWAsIGBmaWx0ZXJgLCBhbmQgYGxheW91dGAgcHJvcGVydGllcyBmcm9tLiBUaGlzIGFsbG93cyB0aGUgbGF5ZXJzIHRvIHNoYXJlIHByb2Nlc3NpbmcgYW5kIGJlIG1vcmUgZWZmaWNpZW50LlwiXG4gICAgfSxcbiAgICBcInNvdXJjZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTmFtZSBvZiBhIHNvdXJjZSBkZXNjcmlwdGlvbiB0byBiZSB1c2VkIGZvciB0aGlzIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZS1sYXllclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTGF5ZXIgdG8gdXNlIGZyb20gYSB2ZWN0b3IgdGlsZSBzb3VyY2UuIFJlcXVpcmVkIGlmIHRoZSBzb3VyY2Ugc3VwcG9ydHMgbXVsdGlwbGUgbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAyMixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbGF5ZXIgZ2V0cyBwYXJzZWQgYW5kIGFwcGVhcnMgb24uXCJcbiAgICB9LFxuICAgIFwibWF4em9vbVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWF4aW11bSB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsYXllciBnZXRzIHBhcnNlZCBhbmQgYXBwZWFycyBvbi5cIlxuICAgIH0sXG4gICAgXCJpbnRlcmFjdGl2ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRvY1wiOiBcIkVuYWJsZSBxdWVyeWluZyBvZiBmZWF0dXJlIGRhdGEgZnJvbSB0aGlzIGxheWVyIGZvciBpbnRlcmFjdGl2aXR5LlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlXG4gICAgfSxcbiAgICBcImZpbHRlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBleHByZXNzaW9uIHNwZWNpZnlpbmcgY29uZGl0aW9ucyBvbiBzb3VyY2UgZmVhdHVyZXMuIE9ubHkgZmVhdHVyZXMgdGhhdCBtYXRjaCB0aGUgZmlsdGVyIGFyZSBkaXNwbGF5ZWQuXCJcbiAgICB9LFxuICAgIFwibGF5b3V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImxheW91dFwiLFxuICAgICAgXCJkb2NcIjogXCJMYXlvdXQgcHJvcGVydGllcyBmb3IgdGhlIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInBhaW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkRlZmF1bHQgcGFpbnQgcHJvcGVydGllcyBmb3IgdGhpcyBsYXllci5cIlxuICAgIH0sXG4gICAgXCJwYWludC4qXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkNsYXNzLXNwZWNpZmljIHBhaW50IHByb3BlcnRpZXMgZm9yIHRoaXMgbGF5ZXIuIFRoZSBjbGFzcyBuYW1lIGlzIHRoZSBwYXJ0IGFmdGVyIHRoZSBmaXJzdCBkb3QuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0XCI6IFtcbiAgICBcImxheW91dF9maWxsXCIsXG4gICAgXCJsYXlvdXRfbGluZVwiLFxuICAgIFwibGF5b3V0X3N5bWJvbFwiLFxuICAgIFwibGF5b3V0X3Jhc3RlclwiLFxuICAgIFwibGF5b3V0X2JhY2tncm91bmRcIlxuICBdLFxuICBcImxheW91dF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9maWxsXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9saW5lXCI6IHtcbiAgICBcImxpbmUtY2FwXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJidXR0XCIsXG4gICAgICAgIFwicm91bmRcIixcbiAgICAgICAgXCJzcXVhcmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImJ1dHRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgbGluZSBlbmRpbmdzLlwiXG4gICAgfSxcbiAgICBcImxpbmUtam9pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiYmV2ZWxcIixcbiAgICAgICAgXCJyb3VuZFwiLFxuICAgICAgICBcIm1pdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJtaXRlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiBsaW5lcyB3aGVuIGpvaW5pbmcuXCJcbiAgICB9LFxuICAgIFwibGluZS1taXRlci1saW1pdFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJVc2VkIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCBtaXRlciBqb2lucyB0byBiZXZlbCBqb2lucyBmb3Igc2hhcnAgYW5nbGVzLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcImxpbmUtam9pblwiOiBcIm1pdGVyXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXJvdW5kLWxpbWl0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlVzZWQgdG8gYXV0b21hdGljYWxseSBjb252ZXJ0IHJvdW5kIGpvaW5zIHRvIG1pdGVyIGpvaW5zIGZvciBzaGFsbG93IGFuZ2xlcy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJsaW5lLWpvaW5cIjogXCJyb3VuZFwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3N5bWJvbFwiOiB7XG4gICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgICBcInBvaW50XCIsXG4gICAgICAgICAgXCJsaW5lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJwb2ludFwiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBwbGFjZW1lbnQgcmVsYXRpdmUgdG8gaXRzIGdlb21ldHJ5LiBgbGluZWAgY2FuIG9ubHkgYmUgdXNlZCBvbiBMaW5lU3RyaW5ncyBhbmQgUG9seWdvbnMuXCJcbiAgICB9LFxuICAgIFwic3ltYm9sLW1pbi1kaXN0YW5jZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyNTAsXG4gICAgICBcIm1pbmltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzeW1ib2wgYW5jaG9ycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IFwibGluZVwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwic3ltYm9sLWF2b2lkLWVkZ2VzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgIFwiZG9jXCI6IFwiSWYgdHJ1ZSwgdGhlIHN5bWJvbHMgd2lsbCBub3QgY3Jvc3MgdGlsZSBlZGdlcyB0byBhdm9pZCBtdXR1YWwgY29sbGlzaW9ucy4gUmVjb21tZW5kZWQgaW4gbGF5ZXJzIHRoYXQgZG9uJ3QgaGF2ZSBlbm91Z2ggcGFkZGluZyBpbiB0aGUgdmVjdG9yIHRpbGUgdG8gcHJldmVudCBjb2xsaXNpb25zLCBvciBpZiBpdCBpcyBhIHBvaW50IHN5bWJvbCBsYXllciBwbGFjZWQgYWZ0ZXIgYSBsaW5lIHN5bWJvbCBsYXllci5cIlxuICAgIH0sXG4gICAgXCJpY29uLWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCB0ZXh0LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taWdub3JlLXBsYWNlbWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIHdvbid0IGFmZmVjdCBwbGFjZW1lbnQgb2Ygb3RoZXIgaWNvbnMgYW5kIHRleHQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgaWNvbiwgaW4gc3BhY2VzIHdoZXJlIHRoZSBpY29uIHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIHdoZW4gbWFwIGlzIHJvdGF0ZWQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1tYXgtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIGZhY3RvciB0byBzY2FsZSB0aGUgaWNvbi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkb2NcIjogXCJBIHN0cmluZyB3aXRoIHt0b2tlbnN9IHJlcGxhY2VkLCByZWZlcmVuY2luZyB0aGUgZGF0YSBwcm9wZXJ0eSB0byBwdWxsIGZyb20uXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlXG4gICAgfSxcbiAgICBcImljb24tcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSBpY29uIGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCBpY29uIGJvdW5kaW5nIGJveCB0byBhdm9pZCBpY29uIGNvbGxpc2lvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1rZWVwLXVwcmlnaHRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiBtYXkgYmUgZmxpcHBlZCB0byBwcmV2ZW50IGl0IGZyb20gYmVpbmcgcmVuZGVyZWQgdXBzaWRlLWRvd25cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAge1xuICAgICAgICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSWNvbidzIG9mZnNldCBkaXN0YW5jZS4gVmFsdWVzIGFyZSBbeCwgeV0gd2hlcmUgbmVnYXRpdmVzIGluZGljYXRlIGxlZnQgYW5kIHVwLCByZXNwZWN0aXZlbHkuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIG9yIHRleHQgd2hlbiBtYXAgaXMgcm90YXRlZC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWZpZWxkXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJWYWx1ZSB0byB1c2UgZm9yIGEgdGV4dCBsYWJlbC4gRmVhdHVyZSBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdG9rZW5zIGxpa2Uge2ZpZWxkX25hbWV9LlwiXG4gICAgfSxcbiAgICBcInRleHQtZm9udFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIk9wZW4gU2FucyBSZWd1bGFyLCBBcmlhbCBVbmljb2RlIE1TIFJlZ3VsYXJcIixcbiAgICAgIFwiZG9jXCI6IFwiRm9udCBzdGFjayB0byB1c2UgZm9yIGRpc3BsYXlpbmcgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIHNpemUgdGV4dCB3aWxsIGJlIGxhaWQgb3V0LCB0byBjYWxjdWxhdGUgY29sbGlzaW9ucyB3aXRoLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtbWF4LXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE1LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gbGluZSB3aWR0aCBmb3IgdGV4dCB3cmFwcGluZy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEuMixcbiAgICAgIFwidW5pdHNcIjogXCJlbVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJUZXh0IGxlYWRpbmcgdmFsdWUgZm9yIG11bHRpLWxpbmUgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBrZXJuaW5nIHZhbHVlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtanVzdGlmeVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibGVmdFwiLFxuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcInJpZ2h0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJjZW50ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBqdXN0aWZpY2F0aW9uIG9wdGlvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcImxlZnRcIixcbiAgICAgICAgXCJyaWdodFwiLFxuICAgICAgICBcInRvcFwiLFxuICAgICAgICBcImJvdHRvbVwiLFxuICAgICAgICBcInRvcC1sZWZ0XCIsXG4gICAgICAgIFwidG9wLXJpZ2h0XCIsXG4gICAgICAgIFwiYm90dG9tLWxlZnRcIixcbiAgICAgICAgXCJib3R0b20tcmlnaHRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImNlbnRlclwiLFxuICAgICAgXCJkb2NcIjogXCJXaGljaCBwYXJ0IG9mIHRoZSB0ZXh0IHRvIHBsYWNlIGNsb3Nlc3QgdG8gdGhlIGFuY2hvci5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1hbmdsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiA0NSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIk1heGltdW0gYW5nbGUgY2hhbmdlIGJldHdlZW4gYWRqYWNlbnQgY2hhcmFjdGVycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwic3ltYm9sLXBsYWNlbWVudFwiOiBcImxpbmVcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSB0ZXh0IGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCB0ZXh0IGJvdW5kaW5nIGJveCB0byBhdm9pZCBsYWJlbCBjb2xsaXNpb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQta2VlcC11cHJpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCBtYXkgYmUgZmxpcHBlZCB2ZXJ0aWNhbGx5IHRvIHByZXZlbnQgaXQgZnJvbSBiZWluZyByZW5kZXJlZCB1cHNpZGUtZG93bi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNmb3JtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJub25lXCIsXG4gICAgICAgIFwidXBwZXJjYXNlXCIsXG4gICAgICAgIFwibG93ZXJjYXNlXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJub25lXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmllcyBob3cgdG8gY2FwaXRhbGl6ZSB0ZXh0LCBzaW1pbGFyIHRvIHRoZSBDU1MgYHRleHQtdHJhbnNmb3JtYCBwcm9wZXJ0eS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW9mZnNldFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGRpc3RhbmNlIHRoYXQgdGV4dCBpcyBvZmZzZXQgZnJvbSBpdHMgYW5jaG9yIGhvcml6b250YWxseSBhbmQgdmVydGljYWxseS5cIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwidW5pdHNcIjogXCJlbXNcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwXG4gICAgICBdLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtYWxsb3ctb3ZlcmxhcFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSB0ZXh0IHdpbGwgYmUgdmlzaWJsZSBldmVuIGlmIGl0IGNvbGxpZGVzIHdpdGggb3RoZXIgaWNvbnMgYW5kIGxhYmVscy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCB3b24ndCBhZmZlY3QgcGxhY2VtZW50IG9mIG90aGVyIGljb25zIGFuZCBsYWJlbHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgdGV4dCwgaW4gc3BhY2VzIHdoZXJlIHRoZSB0ZXh0IHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3Jhc3RlclwiOiB7XG4gICAgXCJ2aXNpYmlsaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJ2aXNpYmxlXCIsXG4gICAgICAgIFwibm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwidmlzaWJsZVwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiB0aGlzIGxheWVyLiBgbm9uZWAgaGlkZXMgdGhpcyBsYXllci5cIlxuICAgIH1cbiAgfSxcbiAgXCJmaWx0ZXJcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJ2YWx1ZVwiOiBcIipcIlxuICB9LFxuICBcImZpbHRlcl9vcGVyYXRvclwiOiB7XG4gICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgIFwidmFsdWVzXCI6IFtcbiAgICAgIFwiPT1cIixcbiAgICAgIFwiIT1cIixcbiAgICAgIFwiPlwiLFxuICAgICAgXCI+PVwiLFxuICAgICAgXCI8XCIsXG4gICAgICBcIjw9XCIsXG4gICAgICBcImluXCIsXG4gICAgICBcIiFpblwiLFxuICAgICAgXCJhbGxcIixcbiAgICAgIFwiYW55XCIsXG4gICAgICBcIm5vbmVcIlxuICAgIF1cbiAgfSxcbiAgXCJnZW9tZXRyeV90eXBlXCI6IHtcbiAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgXCJQb2ludFwiLFxuICAgICAgXCJMaW5lU3RyaW5nXCIsXG4gICAgICBcIlBvbHlnb25cIlxuICAgIF1cbiAgfSxcbiAgXCJmdW5jdGlvblwiOiB7XG4gICAgXCJzdG9wc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBhcnJheSBvZiBzdG9wcy5cIixcbiAgICAgIFwidmFsdWVcIjogXCJmdW5jdGlvbl9zdG9wXCJcbiAgICB9LFxuICAgIFwiYmFzZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIlRoZSBleHBvbmVudGlhbCBiYXNlIG9mIHRoZSBpbnRlcnBvbGF0aW9uIGN1cnZlLiBJdCBjb250cm9scyB0aGUgcmF0ZSBhdCB3aGljaCB0aGUgcmVzdWx0IGluY3JlYXNlcy4gSGlnaGVyIHZhbHVlcyBtYWtlIHRoZSByZXN1bHQgaW5jcmVhc2UgbW9yZSB0b3dhcmRzIHRoZSBoaWdoIGVuZCBvZiB0aGUgcmFuZ2UuIFdpdGggYDFgIHRoZSBzdG9wcyBhcmUgaW50ZXJwb2xhdGVkIGxpbmVhcmx5LlwiXG4gICAgfVxuICB9LFxuICBcImZ1bmN0aW9uX3N0b3BcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgIFwidmFsdWVcIjogW1xuICAgICAgXCJudW1iZXJcIixcbiAgICAgIFwiY29sb3JcIlxuICAgIF0sXG4gICAgXCJsZW5ndGhcIjogMixcbiAgICBcImRvY1wiOiBcIlpvb20gbGV2ZWwgYW5kIHZhbHVlIHBhaXIuXCJcbiAgfSxcbiAgXCJwYWludFwiOiBbXG4gICAgXCJwYWludF9maWxsXCIsXG4gICAgXCJwYWludF9saW5lXCIsXG4gICAgXCJwYWludF9zeW1ib2xcIixcbiAgICBcInBhaW50X3Jhc3RlclwiLFxuICAgIFwicGFpbnRfYmFja2dyb3VuZFwiXG4gIF0sXG4gIFwicGFpbnRfZmlsbFwiOiB7XG4gICAgXCJmaWxsLWFudGlhbGlhc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiV2hldGhlciBvciBub3QgdGhlIGZpbGwgc2hvdWxkIGJlIGFudGlhbGlhc2VkLlwiXG4gICAgfSxcbiAgICBcImZpbGwtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgZ2l2ZW4gdG8gdGhlIGZpbGwgY29sb3IuXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJmaWxsLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBjb2xvciBvZiB0aGUgZmlsbC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLW91dGxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG91dGxpbmUgY29sb3Igb2YgdGhlIGZpbGwuIE1hdGNoZXMgdGhlIHZhbHVlIG9mIGBmaWxsLWNvbG9yYCBpZiB1bnNwZWNpZmllZC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIFwiZmlsbC1hbnRpYWxpYXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZ2VvbWV0cnkncyBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiZmlsbC10cmFuc2xhdGVcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBmaWxscy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9saW5lXCI6IHtcbiAgICBcImxpbmUtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGdlb21ldHJ5J3Mgb2Zmc2V0LiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImxpbmUtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwibGluZS13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiU3Ryb2tlIHRoaWNrbmVzcy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWdhcC13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIkRyYXdzIGEgbGluZSBjYXNpbmcgb3V0c2lkZSBvZiBhIGxpbmUncyBhY3R1YWwgcGF0aC4gVmFsdWUgaW5kaWNhdGVzIHRoZSB3aWR0aCBvZiB0aGUgaW5uZXIgZ2FwLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCJcbiAgICB9LFxuICAgIFwibGluZS1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJCbHVyIGFwcGxpZWQgdG8gdGhlIGxpbmUsIGluIHBpeGVscy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWRhc2hhcnJheVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGxlbmd0aHMgb2YgdGhlIGFsdGVybmF0aW5nIGRhc2hlcyBhbmQgZ2FwcyB0aGF0IGZvcm0gdGhlIGRhc2ggcGF0dGVybi4gVGhlIGxlbmd0aHMgYXJlIGxhdGVyIHNjYWxlZCBieSB0aGUgbGluZSB3aWR0aC4gVG8gY29udmVydCBhIGRhc2ggbGVuZ3RoIHRvIHBpeGVscywgbXVsdGlwbHkgdGhlIGxlbmd0aCBieSB0aGUgY3VycmVudCBsaW5lIHdpZHRoLlwiLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJsaW5lIHdpZHRoc1wiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBsaW5lcy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9zeW1ib2xcIjoge1xuICAgIFwiaWNvbi1vcGFjaXR5XCI6IHtcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGljb24gd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiU2NhbGUgZmFjdG9yIGZvciBpY29uLiAxIGlzIG9yaWdpbmFsIHNpemUsIDMgdHJpcGxlcyB0aGUgc2l6ZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uLiBUaGlzIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBzZGYgaWNvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uJ3MgaGFsby4gSWNvbiBoYWxvcyBjYW4gb25seSBiZSB1c2VkIHdpdGggc2RmIGljb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiRGlzdGFuY2Ugb2YgaGFsbyB0byB0aGUgaWNvbiBvdXRsaW5lLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIG91dCB0aGUgaGFsbyB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBpY29uJ3Mgb2Zmc2V0IGRpc3RhbmNlLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJpY29uLXRyYW5zbGF0ZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIHRleHQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxNixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIkZvbnQgc2l6ZS4gSWYgdW5zcGVjaWZpZWQsIHRoZSB0ZXh0IHdpbGwgYmUgYXMgYmlnIGFzIGFsbG93ZWQgYnkgdGhlIGxheWVyIGRlZmluaXRpb24uXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgY29sb3Igd2l0aCB3aGljaCB0aGUgdGV4dCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiIzAwMDAwMFwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSB0ZXh0J3MgaGFsbywgd2hpY2ggaGVscHMgaXQgc3RhbmQgb3V0IGZyb20gYmFja2dyb3VuZHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJEaXN0YW5jZSBvZiBoYWxvIHRvIHRoZSBmb250IG91dGxpbmUuIE1heCB0ZXh0IGhhbG8gd2lkdGggaXMgMS80IG9mIHRoZSBmb250LXNpemUuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWJsdXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBoYWxvJ3MgZmFkZW91dCBkaXN0YW5jZSB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiLFxuICAgICAgICBcInRleHQtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9XG4gIH0sXG4gIFwicGFpbnRfcmFzdGVyXCI6IHtcbiAgICBcInJhc3Rlci1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgaW1hZ2Ugd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcInJhc3Rlci1odWUtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImRvY1wiOiBcIlJvdGF0ZXMgaHVlcyBhcm91bmQgdGhlIGNvbG9yIHdoZWVsLlwiXG4gICAgfSxcbiAgICBcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSW5jcmVhc2Ugb3IgcmVkdWNlIHRoZSBicmlnaHRuZXNzIG9mIHRoZSBpbWFnZS4gVGhlIHZhbHVlIGlzIHRoZSBtaW5pbXVtIGJyaWdodG5lc3MuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgYnJpZ2h0bmVzcyBvZiB0aGUgaW1hZ2UuIFRoZSB2YWx1ZSBpcyB0aGUgbWF4aW11bSBicmlnaHRuZXNzLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLXNhdHVyYXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgc2F0dXJhdGlvbiBvZiB0aGUgaW1hZ2UuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAtMSxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLWNvbnRyYXN0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJJbmNyZWFzZSBvciByZWR1Y2UgdGhlIGNvbnRyYXN0IG9mIHRoZSBpbWFnZS5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IC0xLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIGR1cmF0aW9uIHdoZW4gYSBuZXcgdGlsZSBpcyBhZGRlZC5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcImJhY2tncm91bmQtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGJhY2tncm91bmQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJiYWNrZ3JvdW5kLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJiYWNrZ3JvdW5kLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk9wdGlvbmFsbHkgYW4gaW1hZ2Ugd2hpY2ggaXMgZHJhd24gYXMgdGhlIGJhY2tncm91bmQuXCJcbiAgICB9LFxuICAgIFwiYmFja2dyb3VuZC1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgYmFja2dyb3VuZCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9XG4gIH0sXG4gIFwidHJhbnNpdGlvblwiOiB7XG4gICAgXCJkdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwidW5pdHNcIjogXCJtaWxsaXNlY29uZHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGltZSBhbGxvdHRlZCBmb3IgdHJhbnNpdGlvbnMgdG8gY29tcGxldGUuXCJcbiAgICB9LFxuICAgIFwiZGVsYXlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJMZW5ndGggb2YgdGltZSBiZWZvcmUgYSB0cmFuc2l0aW9uIGJlZ2lucy5cIlxuICAgIH1cbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBsaWdodHdlaWdodCBCdWZmZXIgc2hpbSBmb3IgcGJmIGJyb3dzZXIgYnVpbGRcbi8vIGJhc2VkIG9uIGNvZGUgZnJvbSBnaXRodWIuY29tL2Zlcm9zcy9idWZmZXIgKE1JVC1saWNlbnNlZClcblxubW9kdWxlLmV4cG9ydHMgPSBCdWZmZXI7XG5cbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpO1xuXG52YXIgQnVmZmVyTWV0aG9kcztcblxuZnVuY3Rpb24gQnVmZmVyKGxlbmd0aCkge1xuICAgIHZhciBhcnI7XG4gICAgaWYgKGxlbmd0aCAmJiBsZW5ndGgubGVuZ3RoKSB7XG4gICAgICAgIGFyciA9IGxlbmd0aDtcbiAgICAgICAgbGVuZ3RoID0gYXJyLmxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCB8fCAwKTtcbiAgICBpZiAoYXJyKSBidWYuc2V0KGFycik7XG5cbiAgICBidWYucmVhZFVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkVUludDMyTEU7XG4gICAgYnVmLndyaXRlVUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG4gICAgYnVmLnJlYWRJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkSW50MzJMRTtcbiAgICBidWYud3JpdGVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEU7XG4gICAgYnVmLnJlYWRGbG9hdExFID0gQnVmZmVyTWV0aG9kcy5yZWFkRmxvYXRMRTtcbiAgICBidWYud3JpdGVGbG9hdExFID0gQnVmZmVyTWV0aG9kcy53cml0ZUZsb2F0TEU7XG4gICAgYnVmLnJlYWREb3VibGVMRSA9IEJ1ZmZlck1ldGhvZHMucmVhZERvdWJsZUxFO1xuICAgIGJ1Zi53cml0ZURvdWJsZUxFID0gQnVmZmVyTWV0aG9kcy53cml0ZURvdWJsZUxFO1xuICAgIGJ1Zi50b1N0cmluZyA9IEJ1ZmZlck1ldGhvZHMudG9TdHJpbmc7XG4gICAgYnVmLndyaXRlID0gQnVmZmVyTWV0aG9kcy53cml0ZTtcbiAgICBidWYuc2xpY2UgPSBCdWZmZXJNZXRob2RzLnNsaWNlO1xuICAgIGJ1Zi5jb3B5ID0gQnVmZmVyTWV0aG9kcy5jb3B5O1xuXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWU7XG4gICAgcmV0dXJuIGJ1Zjtcbn1cblxudmFyIGxhc3RTdHIsIGxhc3RTdHJFbmNvZGVkO1xuXG5CdWZmZXJNZXRob2RzID0ge1xuICAgIHJlYWRVSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSAqIDB4MTAwMDAwMCk7XG4gICAgfSxcblxuICAgIHdyaXRlVUludDMyTEU6IGZ1bmN0aW9uKHZhbCwgcG9zKSB7XG4gICAgICAgIHRoaXNbcG9zXSA9IHZhbDtcbiAgICAgICAgdGhpc1twb3MgKyAxXSA9ICh2YWwgPj4+IDgpO1xuICAgICAgICB0aGlzW3BvcyArIDJdID0gKHZhbCA+Pj4gMTYpO1xuICAgICAgICB0aGlzW3BvcyArIDNdID0gKHZhbCA+Pj4gMjQpO1xuICAgIH0sXG5cbiAgICByZWFkSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSA8PCAyNCk7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdExFOiAgZnVuY3Rpb24ocG9zKSB7IHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgcmVhZERvdWJsZUxFOiBmdW5jdGlvbihwb3MpIHsgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHdyaXRlRmxvYXRMRTogIGZ1bmN0aW9uKHZhbCwgcG9zKSB7IHJldHVybiBpZWVlNzU0LndyaXRlKHRoaXMsIHZhbCwgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgd3JpdGVEb3VibGVMRTogZnVuY3Rpb24odmFsLCBwb3MpIHsgcmV0dXJuIGllZWU3NTQud3JpdGUodGhpcywgdmFsLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHRvU3RyaW5nOiBmdW5jdGlvbihlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICAgICAgICB2YXIgc3RyID0gJycsXG4gICAgICAgICAgICB0bXAgPSAnJztcblxuICAgICAgICBzdGFydCA9IHN0YXJ0IHx8IDA7XG4gICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGVuZ3RoLCBlbmQgfHwgdGhpcy5sZW5ndGgpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2ggPSB0aGlzW2ldO1xuICAgICAgICAgICAgaWYgKGNoIDw9IDB4N0YpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gZGVjb2RlVVJJQ29tcG9uZW50KHRtcCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTtcbiAgICAgICAgICAgICAgICB0bXAgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG1wICs9ICclJyArIGNoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0ciArPSBkZWNvZGVVUklDb21wb25lbnQodG1wKTtcblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICB3cml0ZTogZnVuY3Rpb24oc3RyLCBwb3MpIHtcbiAgICAgICAgdmFyIGJ5dGVzID0gc3RyID09PSBsYXN0U3RyID8gbGFzdFN0ckVuY29kZWQgOiBlbmNvZGVTdHJpbmcoc3RyKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpc1twb3MgKyBpXSA9IGJ5dGVzW2ldO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNsaWNlOiBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpO1xuICAgIH0sXG5cbiAgICBjb3B5OiBmdW5jdGlvbihidWYsIHBvcykge1xuICAgICAgICBwb3MgPSBwb3MgfHwgMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBidWZbcG9zICsgaV0gPSB0aGlzW2ldO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgbGFzdFN0ciA9IHN0cjtcbiAgICBsYXN0U3RyRW5jb2RlZCA9IGVuY29kZVN0cmluZyhzdHIpO1xuICAgIHJldHVybiBsYXN0U3RyRW5jb2RlZC5sZW5ndGg7XG59O1xuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbihidWYpIHtcbiAgICByZXR1cm4gISEoYnVmICYmIGJ1Zi5faXNCdWZmZXIpO1xufTtcblxuZnVuY3Rpb24gZW5jb2RlU3RyaW5nKHN0cikge1xuICAgIHZhciBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICBieXRlcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGMsIGxlYWQ7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSk7IC8vIGNvZGUgcG9pbnRcblxuICAgICAgICBpZiAoYyA+IDB4RDdGRiAmJiBjIDwgMHhFMDAwKSB7XG5cbiAgICAgICAgICAgIGlmIChsZWFkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGMgPCAweERDMDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IGM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYyA9IGxlYWQgLSAweEQ4MDAgPDwgMTAgfCBjIC0gMHhEQzAwIHwgMHgxMDAwMDtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjID4gMHhEQkZGIHx8IChpICsgMSA9PT0gbGVuZ3RoKSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICBlbHNlIGxlYWQgPSBjO1xuXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmIChsZWFkKSB7XG4gICAgICAgICAgICBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpO1xuICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODApIGJ5dGVzLnB1c2goYyk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDgwMCkgYnl0ZXMucHVzaChjID4+IDB4NiB8IDB4QzAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDEwMDAwKSBieXRlcy5wdXNoKGMgPj4gMHhDIHwgMHhFMCwgYyA+PiAweDYgJiAweDNGIHwgMHg4MCwgYyAmIDB4M0YgfCAweDgwKTtcbiAgICAgICAgZWxzZSBieXRlcy5wdXNoKGMgPj4gMHgxMiB8IDB4RjAsIGMgPj4gMHhDICYgMHgzRiB8IDB4ODAsIGMgPj4gMHg2ICYgMHgzRiB8IDB4ODAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgfVxuICAgIHJldHVybiBieXRlcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBQYmY7XG5cbnZhciBCdWZmZXIgPSBnbG9iYWwuQnVmZmVyIHx8IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbmZ1bmN0aW9uIFBiZihidWYpIHtcbiAgICB0aGlzLmJ1ZiA9ICFCdWZmZXIuaXNCdWZmZXIoYnVmKSA/IG5ldyBCdWZmZXIoYnVmIHx8IDApIDogYnVmO1xuICAgIHRoaXMucG9zID0gMDtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMuYnVmLmxlbmd0aDtcbn1cblxuUGJmLlZhcmludCAgPSAwOyAvLyB2YXJpbnQ6IGludDMyLCBpbnQ2NCwgdWludDMyLCB1aW50NjQsIHNpbnQzMiwgc2ludDY0LCBib29sLCBlbnVtXG5QYmYuRml4ZWQ2NCA9IDE7IC8vIDY0LWJpdDogZG91YmxlLCBmaXhlZDY0LCBzZml4ZWQ2NFxuUGJmLkJ5dGVzICAgPSAyOyAvLyBsZW5ndGgtZGVsaW1pdGVkOiBzdHJpbmcsIGJ5dGVzLCBlbWJlZGRlZCBtZXNzYWdlcywgcGFja2VkIHJlcGVhdGVkIGZpZWxkc1xuUGJmLkZpeGVkMzIgPSA1OyAvLyAzMi1iaXQ6IGZsb2F0LCBmaXhlZDMyLCBzZml4ZWQzMlxuXG52YXIgU0hJRlRfTEVGVF8zMiA9ICgxIDw8IDE2KSAqICgxIDw8IDE2KSxcbiAgICBTSElGVF9SSUdIVF8zMiA9IDEgLyBTSElGVF9MRUZUXzMyLFxuICAgIFBPV18yXzYzID0gTWF0aC5wb3coMiwgNjMpO1xuXG5QYmYucHJvdG90eXBlID0ge1xuXG4gICAgZGVzdHJveTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuYnVmID0gbnVsbDtcbiAgICB9LFxuXG4gICAgLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHJlYWRGaWVsZHM6IGZ1bmN0aW9uKHJlYWRGaWVsZCwgcmVzdWx0LCBlbmQpIHtcbiAgICAgICAgZW5kID0gZW5kIHx8IHRoaXMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludCgpLFxuICAgICAgICAgICAgICAgIHRhZyA9IHZhbCA+PiAzLFxuICAgICAgICAgICAgICAgIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG5cbiAgICAgICAgICAgIHJlYWRGaWVsZCh0YWcsIHJlc3VsdCwgdGhpcyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gc3RhcnRQb3MpIHRoaXMuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIHJlYWRNZXNzYWdlOiBmdW5jdGlvbihyZWFkRmllbGQsIHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkRmllbGRzKHJlYWRGaWVsZCwgcmVzdWx0LCB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zKTtcbiAgICB9LFxuXG4gICAgcmVhZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZFVJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFNGaXhlZDMyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgLy8gNjQtYml0IGludCBoYW5kbGluZyBpcyBiYXNlZCBvbiBnaXRodWIuY29tL2Rwdy9ub2RlLWJ1ZmZlci1tb3JlLWludHMgKE1JVC1saWNlbnNlZClcblxuICAgIHJlYWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRVSW50MzJMRSh0aGlzLnBvcykgKyB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRTRml4ZWQ2NDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MpICsgdGhpcy5idWYucmVhZEludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkRmxvYXRMRSh0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZERvdWJsZUxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBidWYgPSB0aGlzLmJ1ZixcbiAgICAgICAgICAgIHZhbCwgYiwgYjAsIGIxLCBiMiwgYjM7XG5cbiAgICAgICAgYjAgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMCA8IDB4ODApIHJldHVybiBiMDsgICAgICAgICAgICAgICAgIGIwID0gYjAgJiAweDdmO1xuICAgICAgICBiMSA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIxIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgPDwgNzsgICAgICAgYjEgPSAoYjEgJiAweDdmKSA8PCA3O1xuICAgICAgICBiMiA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIyIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgfCBiMiA8PCAxNDsgYjIgPSAoYjIgJiAweDdmKSA8PCAxNDtcbiAgICAgICAgYjMgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMyA8IDB4ODApIHJldHVybiBiMCB8IGIxIHwgYjIgfCBiMyA8PCAyMTtcblxuICAgICAgICB2YWwgPSBiMCB8IGIxIHwgYjIgfCAoYjMgJiAweDdmKSA8PCAyMTtcblxuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDA7ICAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwOyAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4NDAwMDAwMDAwMDA7ICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MjAwMDAwMDAwMDAwMDsgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDAwMDAwMDAwOyAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwMDAwMDAwMDsgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgdmFyaW50IG5vdCBtb3JlIHRoYW4gMTAgYnl0ZXMnKTtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICB2YWwgPSB0aGlzLnJlYWRWYXJpbnQoKTtcblxuICAgICAgICBpZiAodmFsIDwgUE9XXzJfNjMpIHJldHVybiB2YWw7XG5cbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zIC0gMjtcbiAgICAgICAgd2hpbGUgKHRoaXMuYnVmW3Bvc10gPT09IDB4ZmYpIHBvcy0tO1xuICAgICAgICBpZiAocG9zIDwgc3RhcnRQb3MpIHBvcyA9IHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhbCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zIC0gc3RhcnRQb3MgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBiID0gfnRoaXMuYnVmW3N0YXJ0UG9zICsgaV0gJiAweDdmO1xuICAgICAgICAgICAgdmFsICs9IGkgPCA0ID8gYiA8PCBpICogNyA6IGIgKiBNYXRoLnBvdygyLCBpICogNyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLXZhbCAtIDE7XG4gICAgfSxcblxuICAgIHJlYWRTVmFyaW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG51bSA9IHRoaXMucmVhZFZhcmludCgpO1xuICAgICAgICByZXR1cm4gbnVtICUgMiA9PT0gMSA/IChudW0gKyAxKSAvIC0yIDogbnVtIC8gMjsgLy8gemlnemFnIGVuY29kaW5nXG4gICAgfSxcblxuICAgIHJlYWRCb29sZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpO1xuICAgIH0sXG5cbiAgICByZWFkU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBzdHIgPSB0aGlzLmJ1Zi50b1N0cmluZygndXRmOCcsIHRoaXMucG9zLCBlbmQpO1xuICAgICAgICB0aGlzLnBvcyA9IGVuZDtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuXG4gICAgcmVhZEJ5dGVzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBidWZmZXIgPSB0aGlzLmJ1Zi5zbGljZSh0aGlzLnBvcywgZW5kKTtcbiAgICAgICAgdGhpcy5wb3MgPSBlbmQ7XG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfSxcblxuICAgIC8vIHZlcmJvc2UgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnM7IGRvZXNuJ3QgYWZmZWN0IGd6aXBwZWQgc2l6ZVxuXG4gICAgcmVhZFBhY2tlZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRWYXJpbnQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU1ZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEJvb2xlYW46IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkQm9vbGVhbigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRGbG9hdCgpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRG91YmxlKCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsIGFyciA9IFtdO1xuICAgICAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcblxuICAgIHNraXA6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHZhbCAmIDB4NztcbiAgICAgICAgaWYgKHR5cGUgPT09IFBiZi5WYXJpbnQpIHdoaWxlICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA+IDB4N2YpIHt9XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT09IFBiZi5CeXRlcykgdGhpcy5wb3MgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zO1xuICAgICAgICBlbHNlIGlmICh0eXBlID09PSBQYmYuRml4ZWQzMikgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkNjQpIHRoaXMucG9zICs9IDg7XG4gICAgICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdVbmltcGxlbWVudGVkIHR5cGU6ICcgKyB0eXBlKTtcbiAgICB9LFxuXG4gICAgLy8gPT09IFdSSVRJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHdyaXRlVGFnOiBmdW5jdGlvbih0YWcsIHR5cGUpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludCgodGFnIDw8IDMpIHwgdHlwZSk7XG4gICAgfSxcblxuICAgIHJlYWxsb2M6IGZ1bmN0aW9uKG1pbikge1xuICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfHwgMTY7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aCA8IHRoaXMucG9zICsgbWluKSBsZW5ndGggKj0gMjtcblxuICAgICAgICBpZiAobGVuZ3RoICE9PSB0aGlzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYnVmLmNvcHkoYnVmKTtcbiAgICAgICAgICAgIHRoaXMuYnVmID0gYnVmO1xuICAgICAgICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZmluaXNoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLnBvcztcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcy5idWYuc2xpY2UoMCwgdGhpcy5sZW5ndGgpO1xuICAgIH0sXG5cbiAgICB3cml0ZUZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlVUludDMyTEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlU0ZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRSh2YWwsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICB9LFxuXG4gICAgd3JpdGVGaXhlZDY0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUludDMyTEUodmFsICYgLTEsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVVSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVTRml4ZWQ2NDogZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVJbnQzMkxFKHZhbCAmIC0xLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YWwgPSArdmFsO1xuXG4gICAgICAgIGlmICh2YWwgPD0gMHg3Zikge1xuICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWw7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgzZmZmKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2MoMik7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAwKSAmIDB4N2YpIHwgMHg4MDtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDcpICYgMHg3Zik7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgxZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygzKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHZhbCA8PSAweGZmZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYyg0KTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAyMSkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zO1xuICAgICAgICAgICAgd2hpbGUgKHZhbCA+PSAweDgwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKHZhbCAmIDB4ZmYpIHwgMHg4MDtcbiAgICAgICAgICAgICAgICB2YWwgLz0gMHg4MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygxKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gdmFsIHwgMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyAtIHBvcyA+IDEwKSB0aHJvdyBuZXcgRXJyb3IoJ0dpdmVuIHZhcmludCBkb2VzblxcJ3QgZml0IGludG8gMTAgYnl0ZXMnKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZVNWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCA8IDAgPyAtdmFsICogMiAtIDEgOiB2YWwgKiAyKTtcbiAgICB9LFxuXG4gICAgd3JpdGVCb29sZWFuOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludChCb29sZWFuKHZhbCkpO1xuICAgIH0sXG5cbiAgICB3cml0ZVN0cmluZzogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgIHN0ciA9IFN0cmluZyhzdHIpO1xuICAgICAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuYnl0ZUxlbmd0aChzdHIpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KGJ5dGVzKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGJ5dGVzKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGUoc3RyLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IGJ5dGVzO1xuICAgIH0sXG5cbiAgICB3cml0ZUZsb2F0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUZsb2F0TEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlRG91YmxlOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZURvdWJsZUxFKHZhbCwgdGhpcy5wb3MpO1xuICAgICAgICB0aGlzLnBvcyArPSA4O1xuICAgIH0sXG5cbiAgICB3cml0ZUJ5dGVzOiBmdW5jdGlvbihidWZmZXIpIHtcbiAgICAgICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGxlbik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHRoaXMuYnVmW3RoaXMucG9zKytdID0gYnVmZmVyW2ldO1xuICAgIH0sXG5cbiAgICB3cml0ZU1lc3NhZ2U6IGZ1bmN0aW9uKHRhZywgZm4sIG9iaikge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkJ5dGVzKTtcblxuICAgICAgICB0aGlzLnBvcysrOyAvLyByZXNlcnZlIDEgYnl0ZSBmb3Igc2hvcnQgbWVzc2FnZSBsZW5ndGhcblxuICAgICAgICAvLyB3cml0ZSB0aGUgbWVzc2FnZSBkaXJlY3RseSB0byB0aGUgYnVmZmVyIGFuZCBzZWUgaG93IG11Y2ggd2FzIHdyaXR0ZW5cbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG4gICAgICAgIGZuKG9iaiwgdGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLnBvcyAtIHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhciB2YXJpbnRMZW4gPVxuICAgICAgICAgICAgbGVuIDw9IDB4N2YgPyAxIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDNmZmYgPyAyIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDFmZmZmZiA/IDMgOlxuICAgICAgICAgICAgbGVuIDw9IDB4ZmZmZmZmZiA/IDQgOiBNYXRoLmNlaWwoTWF0aC5sb2cobGVuKSAvIChNYXRoLkxOMiAqIDcpKTtcblxuICAgICAgICAvLyBpZiAxIGJ5dGUgaXNuJ3QgZW5vdWdoIGZvciBlbmNvZGluZyBtZXNzYWdlIGxlbmd0aCwgc2hpZnQgdGhlIGRhdGEgdG8gdGhlIHJpZ2h0XG4gICAgICAgIGlmICh2YXJpbnRMZW4gPiAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2ModmFyaW50TGVuIC0gMSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5wb3MgLSAxOyBpID49IHN0YXJ0UG9zOyBpLS0pIHRoaXMuYnVmW2kgKyB2YXJpbnRMZW4gLSAxXSA9IHRoaXMuYnVmW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluYWxseSwgd3JpdGUgdGhlIG1lc3NhZ2UgbGVuZ3RoIGluIHRoZSByZXNlcnZlZCBwbGFjZSBhbmQgcmVzdG9yZSB0aGUgcG9zaXRpb25cbiAgICAgICAgdGhpcy5wb3MgPSBzdGFydFBvcyAtIDE7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gbGVuO1xuICAgIH0sXG5cbiAgICB3cml0ZVBhY2tlZFZhcmludDogICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkVmFyaW50LCBhcnIpOyAgIH0sXG4gICAgd3JpdGVQYWNrZWRTVmFyaW50OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZFNWYXJpbnQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkQm9vbGVhbjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRCb29sZWFuLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZEZsb2F0OiAgICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkRmxvYXQsIGFycik7ICAgIH0sXG4gICAgd3JpdGVQYWNrZWREb3VibGU6ICAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZERvdWJsZSwgYXJyKTsgICB9LFxuICAgIHdyaXRlUGFja2VkRml4ZWQzMjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRGaXhlZDMyLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZFNGaXhlZDMyOiBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkU0ZpeGVkMzIsIGFycik7IH0sXG4gICAgd3JpdGVQYWNrZWRGaXhlZDY0OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZEZpeGVkNjQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRTRml4ZWQ2NCwgYXJyKTsgfSxcblxuICAgIHdyaXRlQnl0ZXNGaWVsZDogZnVuY3Rpb24odGFnLCBidWZmZXIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVCeXRlcyhidWZmZXIpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDMyKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQzMih2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDY0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQ2NCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlU1ZhcmludCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVTdHJpbmdGaWVsZDogZnVuY3Rpb24odGFnLCBzdHIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVTdHJpbmcoc3RyKTtcbiAgICB9LFxuICAgIHdyaXRlRmxvYXRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDMyKTtcbiAgICAgICAgdGhpcy53cml0ZUZsb2F0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZURvdWJsZUZpZWxkOiBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkNjQpO1xuICAgICAgICB0aGlzLndyaXRlRG91YmxlKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZUJvb2xlYW5GaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludEZpZWxkKHRhZywgQm9vbGVhbih2YWwpKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiB3cml0ZVBhY2tlZFZhcmludChhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVWYXJpbnQoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNWYXJpbnQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTVmFyaW50KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZsb2F0KGFyciwgcGJmKSAgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGbG9hdChhcnJbaV0pOyAgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZERvdWJsZShhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVEb3VibGUoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEJvb2xlYW4oYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVCb29sZWFuKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkMzIoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDMyKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDMyKGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQzMihhcnJbaV0pOyB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkNjQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDY0KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDY0KGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQ2NChhcnJbaV0pOyB9XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBvaW50O1xuXG5mdW5jdGlvbiBQb2ludCh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xufVxuXG5Qb2ludC5wcm90b3R5cGUgPSB7XG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgdGhpcy55KTsgfSxcblxuICAgIGFkZDogICAgIGZ1bmN0aW9uKHApIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHApOyAgICAgfSxcbiAgICBzdWI6ICAgICBmdW5jdGlvbihwKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3N1YihwKTsgICAgIH0sXG4gICAgbXVsdDogICAgZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0KGspOyAgICB9LFxuICAgIGRpdjogICAgIGZ1bmN0aW9uKGspIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2KGspOyAgICAgfSxcbiAgICByb3RhdGU6ICBmdW5jdGlvbihhKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZShhKTsgIH0sXG4gICAgbWF0TXVsdDogZnVuY3Rpb24obSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tYXRNdWx0KG0pOyB9LFxuICAgIHVuaXQ6ICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCk7IH0sXG4gICAgcGVycDogICAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKTsgfSxcbiAgICByb3VuZDogICBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTsgfSxcblxuICAgIG1hZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQodGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55KTtcbiAgICB9LFxuXG4gICAgZXF1YWxzOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnggPT09IHAueCAmJlxuICAgICAgICAgICAgICAgdGhpcy55ID09PSBwLnk7XG4gICAgfSxcblxuICAgIGRpc3Q6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIocCkpO1xuICAgIH0sXG5cbiAgICBkaXN0U3FyOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHZhciBkeCA9IHAueCAtIHRoaXMueCxcbiAgICAgICAgICAgIGR5ID0gcC55IC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG4gICAgfSxcblxuICAgIGFuZ2xlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpO1xuICAgIH0sXG5cbiAgICBhbmdsZVRvOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMueSAtIGIueSwgdGhpcy54IC0gYi54KTtcbiAgICB9LFxuXG4gICAgYW5nbGVXaXRoOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFuZ2xlV2l0aFNlcChiLngsIGIueSk7XG4gICAgfSxcblxuICAgIC8vIEZpbmQgdGhlIGFuZ2xlIG9mIHRoZSB0d28gdmVjdG9ycywgc29sdmluZyB0aGUgZm9ybXVsYSBmb3IgdGhlIGNyb3NzIHByb2R1Y3QgYSB4IGIgPSB8YXx8YnxzaW4ozrgpIGZvciDOuC5cbiAgICBhbmdsZVdpdGhTZXA6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoXG4gICAgICAgICAgICB0aGlzLnggKiB5IC0gdGhpcy55ICogeCxcbiAgICAgICAgICAgIHRoaXMueCAqIHggKyB0aGlzLnkgKiB5KTtcbiAgICB9LFxuXG4gICAgX21hdE11bHQ6IGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgdmFyIHggPSBtWzBdICogdGhpcy54ICsgbVsxXSAqIHRoaXMueSxcbiAgICAgICAgICAgIHkgPSBtWzJdICogdGhpcy54ICsgbVszXSAqIHRoaXMueTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hZGQ6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54ICs9IHAueDtcbiAgICAgICAgdGhpcy55ICs9IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9zdWI6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54IC09IHAueDtcbiAgICAgICAgdGhpcy55IC09IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9tdWx0OiBmdW5jdGlvbihrKSB7XG4gICAgICAgIHRoaXMueCAqPSBrO1xuICAgICAgICB0aGlzLnkgKj0gaztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kaXY6IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdGhpcy54IC89IGs7XG4gICAgICAgIHRoaXMueSAvPSBrO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3VuaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9kaXYodGhpcy5tYWcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcGVycDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55O1xuICAgICAgICB0aGlzLnkgPSB0aGlzLng7XG4gICAgICAgIHRoaXMueCA9IC15O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdGF0ZTogZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgICAgIHggPSBjb3MgKiB0aGlzLnggLSBzaW4gKiB0aGlzLnksXG4gICAgICAgICAgICB5ID0gc2luICogdGhpcy54ICsgY29zICogdGhpcy55O1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgUG9pbnQgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblBvaW50LmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoYVswXSwgYVsxXSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufTtcbiIsIi8qXG4gKGMpIDIwMTMsIFZsYWRpbWlyIEFnYWZvbmtpblxuIFJCdXNoLCBhIEphdmFTY3JpcHQgbGlicmFyeSBmb3IgaGlnaC1wZXJmb3JtYW5jZSAyRCBzcGF0aWFsIGluZGV4aW5nIG9mIHBvaW50cyBhbmQgcmVjdGFuZ2xlcy5cbiBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9yYnVzaFxuKi9cblxuKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpIHtcblxuICAgIC8vIGpzaGludCBuZXdjYXA6IGZhbHNlLCB2YWxpZHRoaXM6IHRydWVcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgcmJ1c2gpKSByZXR1cm4gbmV3IHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCk7XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgICB0b0JCb3ggPSB0aGlzLnRvQkJveDtcblxuICAgICAgICBpZiAoIWludGVyc2VjdHMoYmJveCwgbm9kZS5iYm94KSkgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICB2YXIgbm9kZXNUb1NlYXJjaCA9IFtdLFxuICAgICAgICAgICAgaSwgbGVuLCBjaGlsZCwgY2hpbGRCQm94O1xuXG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgY2hpbGRCQm94ID0gbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3g7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJzZWN0cyhiYm94LCBjaGlsZEJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGFpbnMoYmJveCwgY2hpbGRCQm94KSkgdGhpcy5fYWxsKGNoaWxkLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBjb2xsaWRlczogZnVuY3Rpb24gKGJib3gpIHtcblxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZGF0YSxcbiAgICAgICAgICAgIHRvQkJveCA9IHRoaXMudG9CQm94O1xuXG4gICAgICAgIGlmICghaW50ZXJzZWN0cyhiYm94LCBub2RlLmJib3gpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZC5iYm94O1xuXG4gICAgICAgICAgICAgICAgaWYgKGludGVyc2VjdHMoYmJveCwgY2hpbGRCQm94KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IGNvbnRhaW5zKGJib3gsIGNoaWxkQkJveCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1RvU2VhcmNoLnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICBsb2FkOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBpZiAoIShkYXRhICYmIGRhdGEubGVuZ3RoKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgdGhpcy5fbWluRW50cmllcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluc2VydChkYXRhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVjdXJzaXZlbHkgYnVpbGQgdGhlIHRyZWUgd2l0aCB0aGUgZ2l2ZW4gZGF0YSBmcm9tIHN0cmF0Y2ggdXNpbmcgT01UIGFsZ29yaXRobVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX2J1aWxkKGRhdGEuc2xpY2UoKSwgMCwgZGF0YS5sZW5ndGggLSAxLCAwKTtcblxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHNhdmUgYXMgaXMgaWYgdHJlZSBpcyBlbXB0eVxuICAgICAgICAgICAgdGhpcy5kYXRhID0gbm9kZTtcblxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPT09IG5vZGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICAvLyBzcGxpdCByb290IGlmIHRyZWVzIGhhdmUgdGhlIHNhbWUgaGVpZ2h0XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLCBub2RlKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPCBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgdHJlZXMgaWYgaW5zZXJ0ZWQgb25lIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgIHZhciB0bXBOb2RlID0gdGhpcy5kYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IHRtcE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGluc2VydCB0aGUgc21hbGwgdHJlZSBpbnRvIHRoZSBsYXJnZSB0cmVlIGF0IGFwcHJvcHJpYXRlIGxldmVsXG4gICAgICAgICAgICB0aGlzLl9pbnNlcnQobm9kZSwgdGhpcy5kYXRhLmhlaWdodCAtIG5vZGUuaGVpZ2h0IC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBpZiAoaXRlbSkgdGhpcy5faW5zZXJ0KGl0ZW0sIHRoaXMuZGF0YS5oZWlnaHQgLSAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgICAgIGJib3g6IGVtcHR5KCksXG4gICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICByZW1vdmU6IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBub2RlLmNoaWxkcmVuLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiBjb250YWlucyhub2RlLmJib3gsIGJib3gpKSB7IC8vIGdvIGRvd25cbiAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bMF07XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50KSB7IC8vIGdvIHJpZ2h0XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBwYXJlbnQuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9IGVsc2Ugbm9kZSA9IG51bGw7IC8vIG5vdGhpbmcgZm91bmRcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICB0b0JCb3g6IGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBpdGVtOyB9LFxuXG4gICAgY29tcGFyZU1pblg6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhWzBdIC0gYlswXTsgfSxcbiAgICBjb21wYXJlTWluWTogZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGFbMV0gLSBiWzFdOyB9LFxuXG4gICAgdG9KU09OOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmRhdGE7IH0sXG5cbiAgICBmcm9tSlNPTjogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hbGw6IGZ1bmN0aW9uIChub2RlLCByZXN1bHQpIHtcbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXTtcbiAgICAgICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgbm9kZS5jaGlsZHJlbik7XG4gICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaC5hcHBseShub2Rlc1RvU2VhcmNoLCBub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgX2J1aWxkOiBmdW5jdGlvbiAoaXRlbXMsIGxlZnQsIHJpZ2h0LCBoZWlnaHQpIHtcblxuICAgICAgICB2YXIgTiA9IHJpZ2h0IC0gbGVmdCArIDEsXG4gICAgICAgICAgICBNID0gdGhpcy5fbWF4RW50cmllcyxcbiAgICAgICAgICAgIG5vZGU7XG5cbiAgICAgICAgaWYgKE4gPD0gTSkge1xuICAgICAgICAgICAgLy8gcmVhY2hlZCBsZWFmIGxldmVsOyByZXR1cm4gbGVhZlxuICAgICAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgICAgICBjaGlsZHJlbjogaXRlbXMuc2xpY2UobGVmdCwgcmlnaHQgKyAxKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgICAgICAgICAgYmJveDogbnVsbCxcbiAgICAgICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgLy8gdGFyZ2V0IGhlaWdodCBvZiB0aGUgYnVsay1sb2FkZWQgdHJlZVxuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGgubG9nKE4pIC8gTWF0aC5sb2coTSkpO1xuXG4gICAgICAgICAgICAvLyB0YXJnZXQgbnVtYmVyIG9mIHJvb3QgZW50cmllcyB0byBtYXhpbWl6ZSBzdG9yYWdlIHV0aWxpemF0aW9uXG4gICAgICAgICAgICBNID0gTWF0aC5jZWlsKE4gLyBNYXRoLnBvdyhNLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPIGVsaW1pbmF0ZSByZWN1cnNpb24/XG5cbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgYmJveDogbnVsbFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNwbGl0IHRoZSBpdGVtcyBpbnRvIE0gbW9zdGx5IHNxdWFyZSB0aWxlc1xuXG4gICAgICAgIHZhciBOMiA9IE1hdGguY2VpbChOIC8gTSksXG4gICAgICAgICAgICBOMSA9IE4yICogTWF0aC5jZWlsKE1hdGguc3FydChNKSksXG4gICAgICAgICAgICBpLCBqLCByaWdodDIsIHJpZ2h0MztcblxuICAgICAgICBtdWx0aVNlbGVjdChpdGVtcywgbGVmdCwgcmlnaHQsIE4xLCB0aGlzLmNvbXBhcmVNaW5YKTtcblxuICAgICAgICBmb3IgKGkgPSBsZWZ0OyBpIDw9IHJpZ2h0OyBpICs9IE4xKSB7XG5cbiAgICAgICAgICAgIHJpZ2h0MiA9IE1hdGgubWluKGkgKyBOMSAtIDEsIHJpZ2h0KTtcblxuICAgICAgICAgICAgbXVsdGlTZWxlY3QoaXRlbXMsIGksIHJpZ2h0MiwgTjIsIHRoaXMuY29tcGFyZU1pblkpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSBpOyBqIDw9IHJpZ2h0MjsgaiArPSBOMikge1xuXG4gICAgICAgICAgICAgICAgcmlnaHQzID0gTWF0aC5taW4oaiArIE4yIC0gMSwgcmlnaHQyKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgZWFjaCBlbnRyeSByZWN1cnNpdmVseVxuICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4ucHVzaCh0aGlzLl9idWlsZChpdGVtcywgaiwgcmlnaHQzLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjYWxjQkJveChub2RlLCB0aGlzLnRvQkJveCk7XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9jaG9vc2VTdWJ0cmVlOiBmdW5jdGlvbiAoYmJveCwgbm9kZSwgbGV2ZWwsIHBhdGgpIHtcblxuICAgICAgICB2YXIgaSwgbGVuLCBjaGlsZCwgdGFyZ2V0Tm9kZSwgYXJlYSwgZW5sYXJnZW1lbnQsIG1pbkFyZWEsIG1pbkVubGFyZ2VtZW50O1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYgfHwgcGF0aC5sZW5ndGggLSAxID09PSBsZXZlbCkgYnJlYWs7XG5cbiAgICAgICAgICAgIG1pbkFyZWEgPSBtaW5FbmxhcmdlbWVudCA9IEluZmluaXR5O1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShjaGlsZC5iYm94KTtcbiAgICAgICAgICAgICAgICBlbmxhcmdlbWVudCA9IGVubGFyZ2VkQXJlYShiYm94LCBjaGlsZC5iYm94KSAtIGFyZWE7XG5cbiAgICAgICAgICAgICAgICAvLyBjaG9vc2UgZW50cnkgd2l0aCB0aGUgbGVhc3QgYXJlYSBlbmxhcmdlbWVudFxuICAgICAgICAgICAgICAgIGlmIChlbmxhcmdlbWVudCA8IG1pbkVubGFyZ2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkVubGFyZ2VtZW50ID0gZW5sYXJnZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVubGFyZ2VtZW50ID09PSBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIG9uZSB3aXRoIHRoZSBzbWFsbGVzdCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSB0YXJnZXROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9pbnNlcnQ6IGZ1bmN0aW9uIChpdGVtLCBsZXZlbCwgaXNOb2RlKSB7XG5cbiAgICAgICAgdmFyIHRvQkJveCA9IHRoaXMudG9CQm94LFxuICAgICAgICAgICAgYmJveCA9IGlzTm9kZSA/IGl0ZW0uYmJveCA6IHRvQkJveChpdGVtKSxcbiAgICAgICAgICAgIGluc2VydFBhdGggPSBbXTtcblxuICAgICAgICAvLyBmaW5kIHRoZSBiZXN0IG5vZGUgZm9yIGFjY29tbW9kYXRpbmcgdGhlIGl0ZW0sIHNhdmluZyBhbGwgbm9kZXMgYWxvbmcgdGhlIHBhdGggdG9vXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fY2hvb3NlU3VidHJlZShiYm94LCB0aGlzLmRhdGEsIGxldmVsLCBpbnNlcnRQYXRoKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGl0ZW0gaW50byB0aGUgbm9kZVxuICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goaXRlbSk7XG4gICAgICAgIGV4dGVuZChub2RlLmJib3gsIGJib3gpO1xuXG4gICAgICAgIC8vIHNwbGl0IG9uIG5vZGUgb3ZlcmZsb3c7IHByb3BhZ2F0ZSB1cHdhcmRzIGlmIG5lY2Vzc2FyeVxuICAgICAgICB3aGlsZSAobGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAgaWYgKGluc2VydFBhdGhbbGV2ZWxdLmNoaWxkcmVuLmxlbmd0aCA+IHRoaXMuX21heEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zcGxpdChpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgICAgICAgICAgICAgbGV2ZWwtLTtcbiAgICAgICAgICAgIH0gZWxzZSBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBiYm94ZXMgYWxvbmcgdGhlIGluc2VydGlvbiBwYXRoXG4gICAgICAgIHRoaXMuX2FkanVzdFBhcmVudEJCb3hlcyhiYm94LCBpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgfSxcblxuICAgIC8vIHNwbGl0IG92ZXJmbG93ZWQgbm9kZSBpbnRvIHR3b1xuICAgIF9zcGxpdDogZnVuY3Rpb24gKGluc2VydFBhdGgsIGxldmVsKSB7XG5cbiAgICAgICAgdmFyIG5vZGUgPSBpbnNlcnRQYXRoW2xldmVsXSxcbiAgICAgICAgICAgIE0gPSBub2RlLmNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICAgIG0gPSB0aGlzLl9taW5FbnRyaWVzO1xuXG4gICAgICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhub2RlLCBtLCBNKTtcblxuICAgICAgICB2YXIgbmV3Tm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLnNwbGljZSh0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pKSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobm9kZS5sZWFmKSBuZXdOb2RlLmxlYWYgPSB0cnVlO1xuXG4gICAgICAgIGNhbGNCQm94KG5vZGUsIHRoaXMudG9CQm94KTtcbiAgICAgICAgY2FsY0JCb3gobmV3Tm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIGlmIChsZXZlbCkgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIGVsc2UgdGhpcy5fc3BsaXRSb290KG5vZGUsIG5ld05vZGUpO1xuICAgIH0sXG5cbiAgICBfc3BsaXRSb290OiBmdW5jdGlvbiAobm9kZSwgbmV3Tm9kZSkge1xuICAgICAgICAvLyBzcGxpdCByb290IG5vZGVcbiAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtub2RlLCBuZXdOb2RlXSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHQgKyAxXG4gICAgICAgIH07XG4gICAgICAgIGNhbGNCQm94KHRoaXMuZGF0YSwgdGhpcy50b0JCb3gpO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3BsaXRJbmRleDogZnVuY3Rpb24gKG5vZGUsIG0sIE0pIHtcblxuICAgICAgICB2YXIgaSwgYmJveDEsIGJib3gyLCBvdmVybGFwLCBhcmVhLCBtaW5PdmVybGFwLCBtaW5BcmVhLCBpbmRleDtcblxuICAgICAgICBtaW5PdmVybGFwID0gbWluQXJlYSA9IEluZmluaXR5O1xuXG4gICAgICAgIGZvciAoaSA9IG07IGkgPD0gTSAtIG07IGkrKykge1xuICAgICAgICAgICAgYmJveDEgPSBkaXN0QkJveChub2RlLCAwLCBpLCB0aGlzLnRvQkJveCk7XG4gICAgICAgICAgICBiYm94MiA9IGRpc3RCQm94KG5vZGUsIGksIE0sIHRoaXMudG9CQm94KTtcblxuICAgICAgICAgICAgb3ZlcmxhcCA9IGludGVyc2VjdGlvbkFyZWEoYmJveDEsIGJib3gyKTtcbiAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShiYm94MSkgKyBiYm94QXJlYShiYm94Mik7XG5cbiAgICAgICAgICAgIC8vIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIG92ZXJsYXBcbiAgICAgICAgICAgIGlmIChvdmVybGFwIDwgbWluT3ZlcmxhcCkge1xuICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSBvdmVybGFwO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcblxuICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG92ZXJsYXAgPT09IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbmltdW0gYXJlYVxuICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICB9LFxuXG4gICAgLy8gc29ydHMgbm9kZSBjaGlsZHJlbiBieSB0aGUgYmVzdCBheGlzIGZvciBzcGxpdFxuICAgIF9jaG9vc2VTcGxpdEF4aXM6IGZ1bmN0aW9uIChub2RlLCBtLCBNKSB7XG5cbiAgICAgICAgdmFyIGNvbXBhcmVNaW5YID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWCA6IGNvbXBhcmVOb2RlTWluWCxcbiAgICAgICAgICAgIGNvbXBhcmVNaW5ZID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWSA6IGNvbXBhcmVOb2RlTWluWSxcbiAgICAgICAgICAgIHhNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5YKSxcbiAgICAgICAgICAgIHlNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5ZKTtcblxuICAgICAgICAvLyBpZiB0b3RhbCBkaXN0cmlidXRpb25zIG1hcmdpbiB2YWx1ZSBpcyBtaW5pbWFsIGZvciB4LCBzb3J0IGJ5IG1pblgsXG4gICAgICAgIC8vIG90aGVyd2lzZSBpdCdzIGFscmVhZHkgc29ydGVkIGJ5IG1pbllcbiAgICAgICAgaWYgKHhNYXJnaW4gPCB5TWFyZ2luKSBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZU1pblgpO1xuICAgIH0sXG5cbiAgICAvLyB0b3RhbCBtYXJnaW4gb2YgYWxsIHBvc3NpYmxlIHNwbGl0IGRpc3RyaWJ1dGlvbnMgd2hlcmUgZWFjaCBub2RlIGlzIGF0IGxlYXN0IG0gZnVsbFxuICAgIF9hbGxEaXN0TWFyZ2luOiBmdW5jdGlvbiAobm9kZSwgbSwgTSwgY29tcGFyZSkge1xuXG4gICAgICAgIG5vZGUuY2hpbGRyZW4uc29ydChjb21wYXJlKTtcblxuICAgICAgICB2YXIgdG9CQm94ID0gdGhpcy50b0JCb3gsXG4gICAgICAgICAgICBsZWZ0QkJveCA9IGRpc3RCQm94KG5vZGUsIDAsIG0sIHRvQkJveCksXG4gICAgICAgICAgICByaWdodEJCb3ggPSBkaXN0QkJveChub2RlLCBNIC0gbSwgTSwgdG9CQm94KSxcbiAgICAgICAgICAgIG1hcmdpbiA9IGJib3hNYXJnaW4obGVmdEJCb3gpICsgYmJveE1hcmdpbihyaWdodEJCb3gpLFxuICAgICAgICAgICAgaSwgY2hpbGQ7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGV4dGVuZChsZWZ0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4obGVmdEJCb3gpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gTSAtIG0gLSAxOyBpID49IG07IGktLSkge1xuICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgZXh0ZW5kKHJpZ2h0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4ocmlnaHRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXJnaW47XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgZXh0ZW5kKHBhdGhbaV0uYmJveCwgYmJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbmRlbnNlOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIHRoZSBwYXRoLCByZW1vdmluZyBlbXB0eSBub2RlcyBhbmQgdXBkYXRpbmcgYmJveGVzXG4gICAgICAgIGZvciAodmFyIGkgPSBwYXRoLmxlbmd0aCAtIDEsIHNpYmxpbmdzOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKHBhdGhbaV0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzID0gcGF0aFtpIC0gMV0uY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzLnNwbGljZShzaWJsaW5ncy5pbmRleE9mKHBhdGhbaV0pLCAxKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBjYWxjQkJveChwYXRoW2ldLCB0aGlzLnRvQkJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2luaXRGb3JtYXQ6IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgLy8gZGF0YSBmb3JtYXQgKG1pblgsIG1pblksIG1heFgsIG1heFkgYWNjZXNzb3JzKVxuXG4gICAgICAgIC8vIHVzZXMgZXZhbC10eXBlIGZ1bmN0aW9uIGNvbXBpbGF0aW9uIGluc3RlYWQgb2YganVzdCBhY2NlcHRpbmcgYSB0b0JCb3ggZnVuY3Rpb25cbiAgICAgICAgLy8gYmVjYXVzZSB0aGUgYWxnb3JpdGhtcyBhcmUgdmVyeSBzZW5zaXRpdmUgdG8gc29ydGluZyBmdW5jdGlvbnMgcGVyZm9ybWFuY2UsXG4gICAgICAgIC8vIHNvIHRoZXkgc2hvdWxkIGJlIGRlYWQgc2ltcGxlIGFuZCB3aXRob3V0IGlubmVyIGNhbGxzXG5cbiAgICAgICAgLy8ganNoaW50IGV2aWw6IHRydWVcblxuICAgICAgICB2YXIgY29tcGFyZUFyciA9IFsncmV0dXJuIGEnLCAnIC0gYicsICc7J107XG5cbiAgICAgICAgdGhpcy5jb21wYXJlTWluWCA9IG5ldyBGdW5jdGlvbignYScsICdiJywgY29tcGFyZUFyci5qb2luKGZvcm1hdFswXSkpO1xuICAgICAgICB0aGlzLmNvbXBhcmVNaW5ZID0gbmV3IEZ1bmN0aW9uKCdhJywgJ2InLCBjb21wYXJlQXJyLmpvaW4oZm9ybWF0WzFdKSk7XG5cbiAgICAgICAgdGhpcy50b0JCb3ggPSBuZXcgRnVuY3Rpb24oJ2EnLCAncmV0dXJuIFthJyArIGZvcm1hdC5qb2luKCcsIGEnKSArICddOycpO1xuICAgIH1cbn07XG5cblxuLy8gY2FsY3VsYXRlIG5vZGUncyBiYm94IGZyb20gYmJveGVzIG9mIGl0cyBjaGlsZHJlblxuZnVuY3Rpb24gY2FsY0JCb3gobm9kZSwgdG9CQm94KSB7XG4gICAgbm9kZS5iYm94ID0gZGlzdEJCb3gobm9kZSwgMCwgbm9kZS5jaGlsZHJlbi5sZW5ndGgsIHRvQkJveCk7XG59XG5cbi8vIG1pbiBib3VuZGluZyByZWN0YW5nbGUgb2Ygbm9kZSBjaGlsZHJlbiBmcm9tIGsgdG8gcC0xXG5mdW5jdGlvbiBkaXN0QkJveChub2RlLCBrLCBwLCB0b0JCb3gpIHtcbiAgICB2YXIgYmJveCA9IGVtcHR5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICBleHRlbmQoYmJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgIH1cblxuICAgIHJldHVybiBiYm94O1xufVxuXG5mdW5jdGlvbiBlbXB0eSgpIHsgcmV0dXJuIFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsgfVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGFbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBhWzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSk7XG4gICAgYVsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pO1xuICAgIGFbM10gPSBNYXRoLm1heChhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5YKGEsIGIpIHsgcmV0dXJuIGEuYmJveFswXSAtIGIuYmJveFswXTsgfVxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5ZKGEsIGIpIHsgcmV0dXJuIGEuYmJveFsxXSAtIGIuYmJveFsxXTsgfVxuXG5mdW5jdGlvbiBiYm94QXJlYShhKSAgIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKiAoYVszXSAtIGFbMV0pOyB9XG5mdW5jdGlvbiBiYm94TWFyZ2luKGEpIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKyAoYVszXSAtIGFbMV0pOyB9XG5cbmZ1bmN0aW9uIGVubGFyZ2VkQXJlYShhLCBiKSB7XG4gICAgcmV0dXJuIChNYXRoLm1heChiWzJdLCBhWzJdKSAtIE1hdGgubWluKGJbMF0sIGFbMF0pKSAqXG4gICAgICAgICAgIChNYXRoLm1heChiWzNdLCBhWzNdKSAtIE1hdGgubWluKGJbMV0sIGFbMV0pKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uQXJlYShhLCBiKSB7XG4gICAgdmFyIG1pblggPSBNYXRoLm1heChhWzBdLCBiWzBdKSxcbiAgICAgICAgbWluWSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pLFxuICAgICAgICBtYXhYID0gTWF0aC5taW4oYVsyXSwgYlsyXSksXG4gICAgICAgIG1heFkgPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcblxuICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICBNYXRoLm1heCgwLCBtYXhZIC0gbWluWSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSA8PSBiWzBdICYmXG4gICAgICAgICAgIGFbMV0gPD0gYlsxXSAmJlxuICAgICAgICAgICBiWzJdIDw9IGFbMl0gJiZcbiAgICAgICAgICAgYlszXSA8PSBhWzNdO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RzKGEsIGIpIHtcbiAgICByZXR1cm4gYlswXSA8PSBhWzJdICYmXG4gICAgICAgICAgIGJbMV0gPD0gYVszXSAmJlxuICAgICAgICAgICBiWzJdID49IGFbMF0gJiZcbiAgICAgICAgICAgYlszXSA+PSBhWzFdO1xufVxuXG4vLyBzb3J0IGFuIGFycmF5IHNvIHRoYXQgaXRlbXMgY29tZSBpbiBncm91cHMgb2YgbiB1bnNvcnRlZCBpdGVtcywgd2l0aCBncm91cHMgc29ydGVkIGJldHdlZW4gZWFjaCBvdGhlcjtcbi8vIGNvbWJpbmVzIHNlbGVjdGlvbiBhbGdvcml0aG0gd2l0aCBiaW5hcnkgZGl2aWRlICYgY29ucXVlciBhcHByb2FjaFxuXG5mdW5jdGlvbiBtdWx0aVNlbGVjdChhcnIsIGxlZnQsIHJpZ2h0LCBuLCBjb21wYXJlKSB7XG4gICAgdmFyIHN0YWNrID0gW2xlZnQsIHJpZ2h0XSxcbiAgICAgICAgbWlkO1xuXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgICAgICByaWdodCA9IHN0YWNrLnBvcCgpO1xuICAgICAgICBsZWZ0ID0gc3RhY2sucG9wKCk7XG5cbiAgICAgICAgaWYgKHJpZ2h0IC0gbGVmdCA8PSBuKSBjb250aW51ZTtcblxuICAgICAgICBtaWQgPSBsZWZ0ICsgTWF0aC5jZWlsKChyaWdodCAtIGxlZnQpIC8gbiAvIDIpICogbjtcbiAgICAgICAgc2VsZWN0KGFyciwgbGVmdCwgcmlnaHQsIG1pZCwgY29tcGFyZSk7XG5cbiAgICAgICAgc3RhY2sucHVzaChsZWZ0LCBtaWQsIG1pZCwgcmlnaHQpO1xuICAgIH1cbn1cblxuLy8gRmxveWQtUml2ZXN0IHNlbGVjdGlvbiBhbGdvcml0aG06XG4vLyBzb3J0IGFuIGFycmF5IGJldHdlZW4gbGVmdCBhbmQgcmlnaHQgKGluY2x1c2l2ZSkgc28gdGhhdCB0aGUgc21hbGxlc3QgayBlbGVtZW50cyBjb21lIGZpcnN0ICh1bm9yZGVyZWQpXG5mdW5jdGlvbiBzZWxlY3QoYXJyLCBsZWZ0LCByaWdodCwgaywgY29tcGFyZSkge1xuICAgIHZhciBuLCBpLCB6LCBzLCBzZCwgbmV3TGVmdCwgbmV3UmlnaHQsIHQsIGo7XG5cbiAgICB3aGlsZSAocmlnaHQgPiBsZWZ0KSB7XG4gICAgICAgIGlmIChyaWdodCAtIGxlZnQgPiA2MDApIHtcbiAgICAgICAgICAgIG4gPSByaWdodCAtIGxlZnQgKyAxO1xuICAgICAgICAgICAgaSA9IGsgLSBsZWZ0ICsgMTtcbiAgICAgICAgICAgIHogPSBNYXRoLmxvZyhuKTtcbiAgICAgICAgICAgIHMgPSAwLjUgKiBNYXRoLmV4cCgyICogeiAvIDMpO1xuICAgICAgICAgICAgc2QgPSAwLjUgKiBNYXRoLnNxcnQoeiAqIHMgKiAobiAtIHMpIC8gbikgKiAoaSAtIG4gLyAyIDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBuZXdMZWZ0ID0gTWF0aC5tYXgobGVmdCwgTWF0aC5mbG9vcihrIC0gaSAqIHMgLyBuICsgc2QpKTtcbiAgICAgICAgICAgIG5ld1JpZ2h0ID0gTWF0aC5taW4ocmlnaHQsIE1hdGguZmxvb3IoayArIChuIC0gaSkgKiBzIC8gbiArIHNkKSk7XG4gICAgICAgICAgICBzZWxlY3QoYXJyLCBuZXdMZWZ0LCBuZXdSaWdodCwgaywgY29tcGFyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0ID0gYXJyW2tdO1xuICAgICAgICBpID0gbGVmdDtcbiAgICAgICAgaiA9IHJpZ2h0O1xuXG4gICAgICAgIHN3YXAoYXJyLCBsZWZ0LCBrKTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYXJyW3JpZ2h0XSwgdCkgPiAwKSBzd2FwKGFyciwgbGVmdCwgcmlnaHQpO1xuXG4gICAgICAgIHdoaWxlIChpIDwgaikge1xuICAgICAgICAgICAgc3dhcChhcnIsIGksIGopO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgd2hpbGUgKGNvbXBhcmUoYXJyW2ldLCB0KSA8IDApIGkrKztcbiAgICAgICAgICAgIHdoaWxlIChjb21wYXJlKGFycltqXSwgdCkgPiAwKSBqLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29tcGFyZShhcnJbbGVmdF0sIHQpID09PSAwKSBzd2FwKGFyciwgbGVmdCwgaik7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgc3dhcChhcnIsIGosIHJpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqIDw9IGspIGxlZnQgPSBqICsgMTtcbiAgICAgICAgaWYgKGsgPD0gaikgcmlnaHQgPSBqIC0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoYXJyLCBpLCBqKSB7XG4gICAgdmFyIHRtcCA9IGFycltpXTtcbiAgICBhcnJbaV0gPSBhcnJbal07XG4gICAgYXJyW2pdID0gdG1wO1xufVxuXG5cbi8vIGV4cG9ydCBhcyBBTUQvQ29tbW9uSlMgbW9kdWxlIG9yIGdsb2JhbCB2YXJpYWJsZVxuaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgZGVmaW5lKCdyYnVzaCcsIGZ1bmN0aW9uKCkgeyByZXR1cm4gcmJ1c2g7IH0pO1xuZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpIG1vZHVsZS5leHBvcnRzID0gcmJ1c2g7XG5lbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHNlbGYucmJ1c2ggPSByYnVzaDtcbmVsc2Ugd2luZG93LnJidXNoID0gcmJ1c2g7XG5cbn0pKCk7XG4iLCIvLyBDb3B5cmlnaHQgMjAxNCBTaW1vbiBMeWRlbGxcclxuLy8gWDExICjigJxNSVTigJ0pIExpY2Vuc2VkLiAoU2VlIExJQ0VOU0UuKVxyXG5cclxudm9pZCAoZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkge1xyXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xyXG4gICAgZGVmaW5lKGZhY3RvcnkpXHJcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KClcclxuICB9IGVsc2Uge1xyXG4gICAgcm9vdC5yZXNvbHZlVXJsID0gZmFjdG9yeSgpXHJcbiAgfVxyXG59KHRoaXMsIGZ1bmN0aW9uKCkge1xyXG5cclxuICBmdW5jdGlvbiByZXNvbHZlVXJsKC8qIC4uLnVybHMgKi8pIHtcclxuICAgIHZhciBudW1VcmxzID0gYXJndW1lbnRzLmxlbmd0aFxyXG5cclxuICAgIGlmIChudW1VcmxzID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInJlc29sdmVVcmwgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50OyBnb3Qgbm9uZS5cIilcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYmFzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiYXNlXCIpXHJcbiAgICBiYXNlLmhyZWYgPSBhcmd1bWVudHNbMF1cclxuXHJcbiAgICBpZiAobnVtVXJscyA9PT0gMSkge1xyXG4gICAgICByZXR1cm4gYmFzZS5ocmVmXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImhlYWRcIilbMF1cclxuICAgIGhlYWQuaW5zZXJ0QmVmb3JlKGJhc2UsIGhlYWQuZmlyc3RDaGlsZClcclxuXHJcbiAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpXHJcbiAgICB2YXIgcmVzb2x2ZWRcclxuXHJcbiAgICBmb3IgKHZhciBpbmRleCA9IDE7IGluZGV4IDwgbnVtVXJsczsgaW5kZXgrKykge1xyXG4gICAgICBhLmhyZWYgPSBhcmd1bWVudHNbaW5kZXhdXHJcbiAgICAgIHJlc29sdmVkID0gYS5ocmVmXHJcbiAgICAgIGJhc2UuaHJlZiA9IHJlc29sdmVkXHJcbiAgICB9XHJcblxyXG4gICAgaGVhZC5yZW1vdmVDaGlsZChiYXNlKVxyXG5cclxuICAgIHJldHVybiByZXNvbHZlZFxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc29sdmVVcmxcclxuXHJcbn0pKTtcclxuIiwiLypcbiAqIENvcHlyaWdodCAoQykgMjAwOCBBcHBsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnNcbiAqIGFyZSBtZXQ6XG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodFxuICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGVcbiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIGBgQVMgSVMnJyBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuICogSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSXG4gKiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgQVBQTEUgSU5DLiBPUlxuICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sXG4gKiBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1JcbiAqIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gKiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICpcbiAqIFBvcnRlZCBmcm9tIFdlYmtpdFxuICogaHR0cDovL3N2bi53ZWJraXQub3JnL3JlcG9zaXRvcnkvd2Via2l0L3RydW5rL1NvdXJjZS9XZWJDb3JlL3BsYXRmb3JtL2dyYXBoaWNzL1VuaXRCZXppZXIuaFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gVW5pdEJlemllcjtcblxuZnVuY3Rpb24gVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpIHtcbiAgICAvLyBDYWxjdWxhdGUgdGhlIHBvbHlub21pYWwgY29lZmZpY2llbnRzLCBpbXBsaWNpdCBmaXJzdCBhbmQgbGFzdCBjb250cm9sIHBvaW50cyBhcmUgKDAsMCkgYW5kICgxLDEpLlxuICAgIHRoaXMuY3ggPSAzLjAgKiBwMXg7XG4gICAgdGhpcy5ieCA9IDMuMCAqIChwMnggLSBwMXgpIC0gdGhpcy5jeDtcbiAgICB0aGlzLmF4ID0gMS4wIC0gdGhpcy5jeCAtIHRoaXMuYng7XG5cbiAgICB0aGlzLmN5ID0gMy4wICogcDF5O1xuICAgIHRoaXMuYnkgPSAzLjAgKiAocDJ5IC0gcDF5KSAtIHRoaXMuY3k7XG4gICAgdGhpcy5heSA9IDEuMCAtIHRoaXMuY3kgLSB0aGlzLmJ5O1xuXG4gICAgdGhpcy5wMXggPSBwMXg7XG4gICAgdGhpcy5wMXkgPSBwMnk7XG4gICAgdGhpcy5wMnggPSBwMng7XG4gICAgdGhpcy5wMnkgPSBwMnk7XG59XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWCA9IGZ1bmN0aW9uKHQpIHtcbiAgICAvLyBgYXggdF4zICsgYnggdF4yICsgY3ggdCcgZXhwYW5kZWQgdXNpbmcgSG9ybmVyJ3MgcnVsZS5cbiAgICByZXR1cm4gKCh0aGlzLmF4ICogdCArIHRoaXMuYngpICogdCArIHRoaXMuY3gpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWSA9IGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gKCh0aGlzLmF5ICogdCArIHRoaXMuYnkpICogdCArIHRoaXMuY3kpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVggPSBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuICgzLjAgKiB0aGlzLmF4ICogdCArIDIuMCAqIHRoaXMuYngpICogdCArIHRoaXMuY3g7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zb2x2ZUN1cnZlWCA9IGZ1bmN0aW9uKHgsIGVwc2lsb24pIHtcbiAgICBpZiAodHlwZW9mIGVwc2lsb24gPT09ICd1bmRlZmluZWQnKSBlcHNpbG9uID0gMWUtNjtcblxuICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgaTtcblxuICAgIC8vIEZpcnN0IHRyeSBhIGZldyBpdGVyYXRpb25zIG9mIE5ld3RvbidzIG1ldGhvZCAtLSBub3JtYWxseSB2ZXJ5IGZhc3QuXG4gICAgZm9yICh0MiA9IHgsIGkgPSAwOyBpIDwgODsgaSsrKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0MikgLSB4O1xuICAgICAgICBpZiAoTWF0aC5hYnMoeDIpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIHZhciBkMiA9IHRoaXMuc2FtcGxlQ3VydmVEZXJpdmF0aXZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyhkMikgPCAxZS02KSBicmVhaztcblxuICAgICAgICB0MiA9IHQyIC0geDIgLyBkMjtcbiAgICB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gdGhlIGJpc2VjdGlvbiBtZXRob2QgZm9yIHJlbGlhYmlsaXR5LlxuICAgIHQwID0gMC4wO1xuICAgIHQxID0gMS4wO1xuICAgIHQyID0geDtcblxuICAgIGlmICh0MiA8IHQwKSByZXR1cm4gdDA7XG4gICAgaWYgKHQyID4gdDEpIHJldHVybiB0MTtcblxuICAgIHdoaWxlICh0MCA8IHQxKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyh4MiAtIHgpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIGlmICh4ID4geDIpIHtcbiAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0MSA9IHQyO1xuICAgICAgICB9XG5cbiAgICAgICAgdDIgPSAodDEgLSB0MCkgKiAwLjUgKyB0MDtcbiAgICB9XG5cbiAgICAvLyBGYWlsdXJlLlxuICAgIHJldHVybiB0Mjtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNvbHZlID0gZnVuY3Rpb24oeCwgZXBzaWxvbikge1xuICAgIHJldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHgsIGVwc2lsb24pKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cy5WZWN0b3JUaWxlID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCcuL2xpYi92ZWN0b3J0aWxlZmVhdHVyZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUxheWVyID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZWxheWVyLmpzJyk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlTGF5ZXIgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGVsYXllcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZlY3RvclRpbGU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGUocGJmLCBlbmQpIHtcbiAgICB0aGlzLmxheWVycyA9IHBiZi5yZWFkRmllbGRzKHJlYWRUaWxlLCB7fSwgZW5kKTtcbn1cblxuZnVuY3Rpb24gcmVhZFRpbGUodGFnLCBsYXllcnMsIHBiZikge1xuICAgIGlmICh0YWcgPT09IDMpIHtcbiAgICAgICAgdmFyIGxheWVyID0gbmV3IFZlY3RvclRpbGVMYXllcihwYmYsIHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zKTtcbiAgICAgICAgaWYgKGxheWVyLmxlbmd0aCkgbGF5ZXJzW2xheWVyLm5hbWVdID0gbGF5ZXI7XG4gICAgfVxufVxuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmVjdG9yVGlsZUZlYXR1cmU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVGZWF0dXJlKHBiZiwgZW5kLCBleHRlbnQsIGtleXMsIHZhbHVlcykge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMucHJvcGVydGllcyA9IHt9O1xuICAgIHRoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIHRoaXMudHlwZSA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fcGJmID0gcGJmO1xuICAgIHRoaXMuX2dlb21ldHJ5ID0gLTE7XG4gICAgdGhpcy5fa2V5cyA9IGtleXM7XG4gICAgdGhpcy5fdmFsdWVzID0gdmFsdWVzO1xuXG4gICAgcGJmLnJlYWRGaWVsZHMocmVhZEZlYXR1cmUsIHRoaXMsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRGZWF0dXJlKHRhZywgZmVhdHVyZSwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PSAxKSBmZWF0dXJlLl9pZCA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgZWxzZSBpZiAodGFnID09IDIpIHJlYWRUYWcocGJmLCBmZWF0dXJlKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gMykgZmVhdHVyZS50eXBlID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gNCkgZmVhdHVyZS5fZ2VvbWV0cnkgPSBwYmYucG9zO1xufVxuXG5mdW5jdGlvbiByZWFkVGFnKHBiZiwgZmVhdHVyZSkge1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhciBrZXkgPSBmZWF0dXJlLl9rZXlzW3BiZi5yZWFkVmFyaW50KCldLFxuICAgICAgICAgICAgdmFsdWUgPSBmZWF0dXJlLl92YWx1ZXNbcGJmLnJlYWRWYXJpbnQoKV07XG4gICAgICAgIGZlYXR1cmUucHJvcGVydGllc1trZXldID0gdmFsdWU7XG4gICAgfVxufVxuXG5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyA9IFsnVW5rbm93bicsICdQb2ludCcsICdMaW5lU3RyaW5nJywgJ1BvbHlnb24nXTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIGxpbmVzID0gW10sXG4gICAgICAgIGxpbmU7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGNtZExlbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgICAgICAgICBjbWQgPSBjbWRMZW4gJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRMZW4gPj4gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGxlbmd0aC0tO1xuXG4gICAgICAgIGlmIChjbWQgPT09IDEgfHwgY21kID09PSAyKSB7XG4gICAgICAgICAgICB4ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgeSArPSBwYmYucmVhZFNWYXJpbnQoKTtcblxuICAgICAgICAgICAgaWYgKGNtZCA9PT0gMSkgeyAvLyBtb3ZlVG9cbiAgICAgICAgICAgICAgICBpZiAobGluZSkgbGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUucHVzaChuZXcgUG9pbnQoeCwgeSkpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kID09PSA3KSB7XG4gICAgICAgICAgICBsaW5lLnB1c2gobGluZVswXS5jbG9uZSgpKTsgLy8gY2xvc2VQb2x5Z29uXG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxpbmUpIGxpbmVzLnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gbGluZXM7XG59O1xuXG5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgY21kTGVuID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZExlbiAmIDB4NztcbiAgICAgICAgICAgIGxlbmd0aCA9IGNtZExlbiA+PiAzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVuZ3RoLS07XG5cbiAgICAgICAgaWYgKGNtZCA9PT0gMSB8fCBjbWQgPT09IDIpIHtcbiAgICAgICAgICAgIHggKz0gcGJmLnJlYWRTVmFyaW50KCk7XG4gICAgICAgICAgICB5ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgaWYgKHggPCB4MSkgeDEgPSB4O1xuICAgICAgICAgICAgaWYgKHggPiB4MikgeDIgPSB4O1xuICAgICAgICAgICAgaWYgKHkgPCB5MSkgeTEgPSB5O1xuICAgICAgICAgICAgaWYgKHkgPiB5MikgeTIgPSB5O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kICE9PSA3KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vua25vd24gY29tbWFuZCAnICsgY21kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbeDEsIHkxLCB4MiwgeTJdO1xufTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZXh0ZW50ICogTWF0aC5wb3coMiwgeiksXG4gICAgICAgIHgwID0gdGhpcy5leHRlbnQgKiB4LFxuICAgICAgICB5MCA9IHRoaXMuZXh0ZW50ICogeSxcbiAgICAgICAgY29vcmRzID0gdGhpcy5sb2FkR2VvbWV0cnkoKSxcbiAgICAgICAgdHlwZSA9IFZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW3RoaXMudHlwZV07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGNvb3Jkc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsaW5lLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGxpbmVbal0sIHkyID0gMTgwIC0gKHAueSArIHkwKSAqIDM2MCAvIHNpemU7XG4gICAgICAgICAgICBsaW5lW2pdID0gW1xuICAgICAgICAgICAgICAgIChwLnggKyB4MCkgKiAzNjAgLyBzaXplIC0gMTgwLFxuICAgICAgICAgICAgICAgIDM2MCAvIE1hdGguUEkgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIgKiBNYXRoLlBJIC8gMTgwKSkgLSA5MFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnUG9pbnQnICYmIGNvb3Jkcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY29vcmRzID0gY29vcmRzWzBdWzBdO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgICAgIHR5cGUgPSAnTXVsdGlQb2ludCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycgJiYgY29vcmRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycpIHtcbiAgICAgICAgdHlwZSA9ICdNdWx0aUxpbmVTdHJpbmcnO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHNcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZSA9IHJlcXVpcmUoJy4vdmVjdG9ydGlsZWZlYXR1cmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVMYXllcihwYmYsIGVuZCkge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMudmVyc2lvbiA9IDE7XG4gICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICB0aGlzLmV4dGVudCA9IDQwOTY7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuXG4gICAgLy8gUHJpdmF0ZVxuICAgIHRoaXMuX3BiZiA9IHBiZjtcbiAgICB0aGlzLl9rZXlzID0gW107XG4gICAgdGhpcy5fdmFsdWVzID0gW107XG4gICAgdGhpcy5fZmVhdHVyZXMgPSBbXTtcblxuICAgIHBiZi5yZWFkRmllbGRzKHJlYWRMYXllciwgdGhpcywgZW5kKTtcblxuICAgIHRoaXMubGVuZ3RoID0gdGhpcy5fZmVhdHVyZXMubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiByZWFkTGF5ZXIodGFnLCBsYXllciwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMTUpIGxheWVyLnZlcnNpb24gPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMSkgbGF5ZXIubmFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSA1KSBsYXllci5leHRlbnQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgbGF5ZXIuX2ZlYXR1cmVzLnB1c2gocGJmLnBvcyk7XG4gICAgZWxzZSBpZiAodGFnID09PSAzKSBsYXllci5fa2V5cy5wdXNoKHBiZi5yZWFkU3RyaW5nKCkpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgbGF5ZXIuX3ZhbHVlcy5wdXNoKHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSB7XG4gICAgdmFyIHZhbHVlID0gbnVsbCxcbiAgICAgICAgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICB2YXIgdGFnID0gcGJmLnJlYWRWYXJpbnQoKSA+PiAzO1xuXG4gICAgICAgIHZhbHVlID0gdGFnID09PSAxID8gcGJmLnJlYWRTdHJpbmcoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDIgPyBwYmYucmVhZEZsb2F0KCkgOlxuICAgICAgICAgICAgdGFnID09PSAzID8gcGJmLnJlYWREb3VibGUoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDQgPyBwYmYucmVhZFZhcmludDY0KCkgOlxuICAgICAgICAgICAgdGFnID09PSA1ID8gcGJmLnJlYWRWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDYgPyBwYmYucmVhZFNWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDcgPyBwYmYucmVhZEJvb2xlYW4oKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufVxuXG4vLyByZXR1cm4gZmVhdHVyZSBgaWAgZnJvbSB0aGlzIGxheWVyIGFzIGEgYFZlY3RvclRpbGVGZWF0dXJlYFxuVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5mZWF0dXJlID0gZnVuY3Rpb24oaSkge1xuICAgIGlmIChpIDwgMCB8fCBpID49IHRoaXMuX2ZlYXR1cmVzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHMnKTtcblxuICAgIHRoaXMuX3BiZi5wb3MgPSB0aGlzLl9mZWF0dXJlc1tpXTtcblxuICAgIHZhciBlbmQgPSB0aGlzLl9wYmYucmVhZFZhcmludCgpICsgdGhpcy5fcGJmLnBvcztcbiAgICByZXR1cm4gbmV3IFZlY3RvclRpbGVGZWF0dXJlKHRoaXMuX3BiZiwgZW5kLCB0aGlzLmV4dGVudCwgdGhpcy5fa2V5cywgdGhpcy5fdmFsdWVzKTtcbn07XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsInZhciBidW5kbGVGbiA9IGFyZ3VtZW50c1szXTtcbnZhciBzb3VyY2VzID0gYXJndW1lbnRzWzRdO1xudmFyIGNhY2hlID0gYXJndW1lbnRzWzVdO1xuXG52YXIgc3RyaW5naWZ5ID0gSlNPTi5zdHJpbmdpZnk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICB2YXIgd2tleTtcbiAgICB2YXIgY2FjaGVLZXlzID0gT2JqZWN0LmtleXMoY2FjaGUpO1xuICAgIFxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2FjaGVLZXlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICBpZiAoY2FjaGVba2V5XS5leHBvcnRzID09PSBmbikge1xuICAgICAgICAgICAgd2tleSA9IGtleTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlmICghd2tleSkge1xuICAgICAgICB3a2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgICAgIHZhciB3Y2FjaGUgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjYWNoZUtleXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICAgICAgd2NhY2hlW2tleV0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgICAgc291cmNlc1t3a2V5XSA9IFtcbiAgICAgICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZScsJ21vZHVsZScsJ2V4cG9ydHMnXSwgJygnICsgZm4gKyAnKShzZWxmKScpLFxuICAgICAgICAgICAgd2NhY2hlXG4gICAgICAgIF07XG4gICAgfVxuICAgIHZhciBza2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgXG4gICAgdmFyIHNjYWNoZSA9IHt9OyBzY2FjaGVbd2tleV0gPSB3a2V5O1xuICAgIHNvdXJjZXNbc2tleV0gPSBbXG4gICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZSddLCdyZXF1aXJlKCcgKyBzdHJpbmdpZnkod2tleSkgKyAnKShzZWxmKScpLFxuICAgICAgICBzY2FjaGVcbiAgICBdO1xuICAgIFxuICAgIHZhciBzcmMgPSAnKCcgKyBidW5kbGVGbiArICcpKHsnXG4gICAgICAgICsgT2JqZWN0LmtleXMoc291cmNlcykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdpZnkoa2V5KSArICc6WydcbiAgICAgICAgICAgICAgICArIHNvdXJjZXNba2V5XVswXVxuICAgICAgICAgICAgICAgICsgJywnICsgc3RyaW5naWZ5KHNvdXJjZXNba2V5XVsxXSkgKyAnXSdcbiAgICAgICAgICAgIDtcbiAgICAgICAgfSkuam9pbignLCcpXG4gICAgICAgICsgJ30se30sWycgKyBzdHJpbmdpZnkoc2tleSkgKyAnXSknXG4gICAgO1xuICAgIFxuICAgIHZhciBVUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkwgfHwgd2luZG93Lm1velVSTCB8fCB3aW5kb3cubXNVUkw7XG4gICAgXG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoVVJMLmNyZWF0ZU9iamVjdFVSTChcbiAgICAgICAgbmV3IEJsb2IoW3NyY10sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSlcbiAgICApKTtcbn07XG4iXX0= (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.mapboxgl = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 'use strict'; // a simple wrapper around a single arraybuffer module.exports = Buffer; function Buffer(buffer) { if (!buffer) { this.array = new ArrayBuffer(this.defaultLength); this.length = this.defaultLength; this.setupViews(); } else { // we only recreate buffers after receiving them from workers for binding to gl, // so we only need these 2 properties this.array = buffer.array; this.pos = buffer.pos; } } Buffer.prototype = { pos: 0, itemSize: 4, // bytes in one item defaultLength: 8192, // initial buffer size arrayType: 'ARRAY_BUFFER', // gl buffer type get index() { return this.pos / this.itemSize; }, setupViews: function() { // set up views for each type to add data of different types to the same buffer this.ubytes = new Uint8Array(this.array); this.bytes = new Int8Array(this.array); this.ushorts = new Uint16Array(this.array); this.shorts = new Int16Array(this.array); }, // binds the buffer to a webgl context bind: function(gl) { var type = gl[this.arrayType]; if (!this.buffer) { this.buffer = gl.createBuffer(); gl.bindBuffer(type, this.buffer); gl.bufferData(type, this.array.slice(0, this.pos), gl.STATIC_DRAW); // dump array buffer once it's bound to gl this.array = null; } else { gl.bindBuffer(type, this.buffer); } }, destroy: function(gl) { if (this.buffer) { gl.deleteBuffer(this.buffer); } }, // increase the buffer size by 50% if a new item doesn't fit resize: function() { if (this.length < this.pos + this.itemSize) { while (this.length < this.pos + this.itemSize) { // increase the length by 50% but keep it even this.length = Math.round(this.length * 1.5 / 2) * 2; } // array buffers can't be resized, so we create a new one and reset all bytes there this.array = new ArrayBuffer(this.length); var ubytes = new Uint8Array(this.array); ubytes.set(this.ubytes); this.setupViews(); } } }; },{}],2:[function(require,module,exports){ 'use strict'; var LineVertexBuffer = require('./line_vertex_buffer'); var LineElementBuffer = require('./line_element_buffer'); var FillVertexBuffer = require('./fill_vertex_buffer'); var FillElementBuffer = require('./triangle_element_buffer'); var OutlineElementBuffer = require('./outline_elements_buffer'); var GlyphVertexBuffer = require('./glyph_vertex_buffer'); var GlyphElementBuffer = require('./triangle_element_buffer'); var IconVertexBuffer = require('./icon_vertex_buffer'); var IconElementBuffer = require('./triangle_element_buffer'); var CollisionBoxVertexBuffer = require('./collision_box_vertex_buffer'); module.exports = function(bufferset) { bufferset = bufferset || {}; return { glyphVertex: new GlyphVertexBuffer(bufferset.glyphVertex), glyphElement: new GlyphElementBuffer(bufferset.glyphElement), iconVertex: new IconVertexBuffer(bufferset.iconVertex), iconElement: new IconElementBuffer(bufferset.iconElement), fillVertex: new FillVertexBuffer(bufferset.fillVertex), fillElement: new FillElementBuffer(bufferset.fillElement), outlineElement: new OutlineElementBuffer(bufferset.outlineElement), lineVertex: new LineVertexBuffer(bufferset.lineVertex), lineElement: new LineElementBuffer(bufferset.lineElement), collisionBoxVertex: new CollisionBoxVertexBuffer(bufferset.collisionBoxVertex) }; }; },{"./collision_box_vertex_buffer":3,"./fill_vertex_buffer":4,"./glyph_vertex_buffer":5,"./icon_vertex_buffer":6,"./line_element_buffer":7,"./line_vertex_buffer":8,"./outline_elements_buffer":9,"./triangle_element_buffer":10}],3:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = CollisionBoxVertexBuffer; function CollisionBoxVertexBuffer(buffer) { Buffer.call(this, buffer); } CollisionBoxVertexBuffer.prototype = util.inherit(Buffer, { itemSize: 12, // bytes per vertex (2 * short + 1 * short + 2 * byte = 8 bytes) defaultLength: 32768, // add a vertex to this buffer; // x, y - vertex position // ex, ey - extrude normal add: function(point, extrude, maxZoom, placementZoom) { var pos = this.pos, pos2 = pos / 2, index = this.index; this.resize(); this.shorts[pos2 + 0] = point.x; this.shorts[pos2 + 1] = point.y; this.shorts[pos2 + 2] = Math.round(extrude.x); this.shorts[pos2 + 3] = Math.round(extrude.y); this.ubytes[pos + 8] = Math.floor(maxZoom * 10); this.ubytes[pos + 9] = Math.floor(placementZoom * 10); this.pos += this.itemSize; return index; } }); },{"../../util/util":96,"./buffer":1}],4:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = FillVertexBuffer; function FillVertexBuffer(buffer) { Buffer.call(this, buffer); } FillVertexBuffer.prototype = util.inherit(Buffer, { itemSize: 4, // bytes per vertex (2 * short == 4 bytes) add: function(x, y) { var pos2 = this.pos / 2; this.resize(); this.shorts[pos2 + 0] = x; this.shorts[pos2 + 1] = y; this.pos += this.itemSize; } }); },{"../../util/util":96,"./buffer":1}],5:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = GlyphVertexBuffer; function GlyphVertexBuffer(buffer) { Buffer.call(this, buffer); } GlyphVertexBuffer.prototype = util.inherit(Buffer, { defaultLength: 2048 * 16, itemSize: 16, add: function(x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom) { var pos = this.pos, pos2 = pos / 2; this.resize(); this.shorts[pos2 + 0] = x; this.shorts[pos2 + 1] = y; this.shorts[pos2 + 2] = Math.round(ox * 64); // use 1/64 pixels for placement this.shorts[pos2 + 3] = Math.round(oy * 64); // a_data1 this.ubytes[pos + 8] /* tex */ = Math.floor(tx / 4); this.ubytes[pos + 9] /* tex */ = Math.floor(ty / 4); this.ubytes[pos + 10] /* labelminzoom */ = Math.floor((labelminzoom) * 10); // a_data2 this.ubytes[pos + 12] /* minzoom */ = Math.floor((minzoom) * 10); // 1/10 zoom levels: z16 == 160. this.ubytes[pos + 13] /* maxzoom */ = Math.floor(Math.min(maxzoom, 25) * 10); // 1/10 zoom levels: z16 == 160. this.pos += this.itemSize; }, bind: function(gl, shader, offset) { Buffer.prototype.bind.call(this, gl); var stride = this.itemSize; gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, offset + 0); gl.vertexAttribPointer(shader.a_offset, 2, gl.SHORT, false, stride, offset + 4); gl.vertexAttribPointer(shader.a_data1, 4, gl.UNSIGNED_BYTE, false, stride, offset + 8); gl.vertexAttribPointer(shader.a_data2, 2, gl.UNSIGNED_BYTE, false, stride, offset + 12); } }); },{"../../util/util":96,"./buffer":1}],6:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = GlyphVertexBuffer; function GlyphVertexBuffer(buffer) { Buffer.call(this, buffer); } GlyphVertexBuffer.prototype = util.inherit(Buffer, { defaultLength: 2048 * 16, itemSize: 16, add: function(x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom) { var pos = this.pos, pos2 = pos / 2; this.resize(); this.shorts[pos2 + 0] = x; this.shorts[pos2 + 1] = y; this.shorts[pos2 + 2] = Math.round(ox * 64); // use 1/64 pixels for placement this.shorts[pos2 + 3] = Math.round(oy * 64); // a_data1 this.ubytes[pos + 8] /* tex */ = tx / 4; this.ubytes[pos + 9] /* tex */ = ty / 4; this.ubytes[pos + 10] /* labelminzoom */ = Math.floor((labelminzoom || 0) * 10); // a_data2 this.ubytes[pos + 12] /* minzoom */ = Math.floor((minzoom || 0) * 10); // 1/10 zoom levels: z16 == 160. this.ubytes[pos + 13] /* maxzoom */ = Math.floor(Math.min(maxzoom || 25, 25) * 10); // 1/10 zoom levels: z16 == 160. this.pos += this.itemSize; }, bind: function(gl, shader, offset) { Buffer.prototype.bind.call(this, gl); var stride = this.itemSize; gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, offset + 0); gl.vertexAttribPointer(shader.a_offset, 2, gl.SHORT, false, stride, offset + 4); gl.vertexAttribPointer(shader.a_data1, 4, gl.UNSIGNED_BYTE, false, stride, offset + 8); gl.vertexAttribPointer(shader.a_data2, 2, gl.UNSIGNED_BYTE, false, stride, offset + 12); } }); },{"../../util/util":96,"./buffer":1}],7:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = LineElementBuffer; function LineElementBuffer(buffer) { Buffer.call(this, buffer); } LineElementBuffer.prototype = util.inherit(Buffer, { itemSize: 6, // bytes per triangle (3 * unsigned short == 6 bytes) arrayType: 'ELEMENT_ARRAY_BUFFER', add: function(a, b, c) { var pos2 = this.pos / 2; this.resize(); this.ushorts[pos2 + 0] = a; this.ushorts[pos2 + 1] = b; this.ushorts[pos2 + 2] = c; this.pos += this.itemSize; } }); },{"../../util/util":96,"./buffer":1}],8:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = LineVertexBuffer; function LineVertexBuffer(buffer) { Buffer.call(this, buffer); } // scale the extrusion vector so that the normal length is this value. // contains the "texture" normals (-1..1). this is distinct from the extrude // normals for line joins, because the x-value remains 0 for the texture // normal array, while the extrude normal actually moves the vertex to create // the acute/bevelled line join. LineVertexBuffer.extrudeScale = 63; LineVertexBuffer.prototype = util.inherit(Buffer, { itemSize: 8, // bytes per vertex (2 * short + 1 * short + 2 * byte = 8 bytes) defaultLength: 32768, // add a vertex to this buffer; // x, y - vertex position // ex, ey - extrude normal // tx, ty - texture normal add: function(point, extrude, tx, ty, linesofar) { var pos = this.pos, pos2 = pos / 2, index = this.index, extrudeScale = LineVertexBuffer.extrudeScale; this.resize(); this.shorts[pos2 + 0] = (Math.floor(point.x) * 2) | tx; this.shorts[pos2 + 1] = (Math.floor(point.y) * 2) | ty; this.bytes[pos + 4] = Math.round(extrudeScale * extrude.x); this.bytes[pos + 5] = Math.round(extrudeScale * extrude.y); this.bytes[pos + 6] = (linesofar || 0) / 128; this.bytes[pos + 7] = (linesofar || 0) % 128; this.pos += this.itemSize; return index; } }); },{"../../util/util":96,"./buffer":1}],9:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = OutlineElementsBuffer; function OutlineElementsBuffer(buffer) { Buffer.call(this, buffer); } OutlineElementsBuffer.prototype = util.inherit(Buffer, { itemSize: 4, // bytes per line (2 * unsigned short == 4 bytes) arrayType: 'ELEMENT_ARRAY_BUFFER', add: function(a, b) { var pos2 = this.pos / 2; this.resize(); this.ushorts[pos2 + 0] = a; this.ushorts[pos2 + 1] = b; this.pos += this.itemSize; } }); },{"../../util/util":96,"./buffer":1}],10:[function(require,module,exports){ 'use strict'; var util = require('../../util/util'); var Buffer = require('./buffer'); module.exports = TriangleElementsBuffer; function TriangleElementsBuffer(buffer) { Buffer.call(this, buffer); } TriangleElementsBuffer.prototype = util.inherit(Buffer, { itemSize: 6, // bytes per triangle (3 * unsigned short == 6 bytes) arrayType: 'ELEMENT_ARRAY_BUFFER', add: function(a, b, c) { var pos2 = this.pos / 2; this.resize(); this.ushorts[pos2 + 0] = a; this.ushorts[pos2 + 1] = b; this.ushorts[pos2 + 2] = c; this.pos += this.itemSize; } }); },{"../../util/util":96,"./buffer":1}],11:[function(require,module,exports){ 'use strict'; module.exports = createBucket; var LineBucket = require('./line_bucket'); var FillBucket = require('./fill_bucket'); var SymbolBucket = require('./symbol_bucket'); var LayoutProperties = require('../style/layout_properties'); var featureFilter = require('feature-filter'); var StyleDeclarationSet = require('../style/style_declaration_set'); function createBucket(layer, buffers, collision, z, overscaling, collisionDebug) { var values = new StyleDeclarationSet('layout', layer.type, layer.layout, {}).values(), fakeZoomHistory = { lastIntegerZoom: Infinity, lastIntegerZoomTime: 0, lastZoom: 0 }, layout = {}; for (var k in values) { layout[k] = values[k].calculate(z, fakeZoomHistory); } var BucketClass = layer.type === 'line' ? LineBucket : layer.type === 'fill' ? FillBucket : layer.type === 'symbol' ? SymbolBucket : null; var bucket = new BucketClass(buffers, new LayoutProperties[layer.type](layout), collision, overscaling, collisionDebug); bucket.id = layer.id; bucket.type = layer.type; bucket['source-layer'] = layer['source-layer']; bucket.interactive = layer.interactive; bucket.minZoom = layer.minzoom; bucket.maxZoom = layer.maxzoom; bucket.filter = featureFilter(layer.filter); bucket.features = []; return bucket; } },{"../style/layout_properties":49,"../style/style_declaration_set":55,"./fill_bucket":14,"./line_bucket":15,"./symbol_bucket":16,"feature-filter":98}],12:[function(require,module,exports){ 'use strict'; module.exports = ElementGroups; function ElementGroups(vertexBuffer, elementBuffer, secondElementBuffer) { this.vertexBuffer = vertexBuffer; this.elementBuffer = elementBuffer; this.secondElementBuffer = secondElementBuffer; this.groups = []; } ElementGroups.prototype.makeRoomFor = function(numVertices) { if (!this.current || this.current.vertexLength + numVertices > 65535) { this.current = new ElementGroup(this.vertexBuffer.index, this.elementBuffer && this.elementBuffer.index, this.secondElementBuffer && this.secondElementBuffer.index); this.groups.push(this.current); } }; function ElementGroup(vertexStartIndex, elementStartIndex, secondElementStartIndex) { // the offset into the vertex buffer of the first vertex in this group this.vertexStartIndex = vertexStartIndex; this.elementStartIndex = elementStartIndex; this.secondElementStartIndex = secondElementStartIndex; this.elementLength = 0; this.vertexLength = 0; this.secondElementLength = 0; } },{}],13:[function(require,module,exports){ 'use strict'; var rbush = require('rbush'); var Point = require('point-geometry'); var vt = require('vector-tile'); var util = require('../util/util'); module.exports = FeatureTree; function FeatureTree(coord, overscaling) { this.x = coord.x; this.y = coord.y; this.z = coord.z - Math.log(overscaling) / Math.LN2; this.rtree = rbush(9); this.toBeInserted = []; } FeatureTree.prototype.insert = function(bbox, layers, feature) { bbox.layers = layers; bbox.feature = feature; this.toBeInserted.push(bbox); }; // bulk insert into tree FeatureTree.prototype._load = function() { this.rtree.load(this.toBeInserted); this.toBeInserted = []; }; // Finds features in this tile at a particular position. FeatureTree.prototype.query = function(args, callback) { if (this.toBeInserted.length) this._load(); var params = args.params || {}, radius = (params.radius || 0) * 4096 / args.scale, x = args.x, y = args.y, result = []; var matching = this.rtree.search([ x - radius, y - radius, x + radius, y + radius ]); for (var i = 0; i < matching.length; i++) { var feature = matching[i].feature, layers = matching[i].layers, type = vt.VectorTileFeature.types[feature.type]; if (params.$type && type !== params.$type) continue; if (!geometryContainsPoint(feature.loadGeometry(), type, new Point(x, y), radius)) continue; var geoJSON = feature.toGeoJSON(this.x, this.y, this.z); for (var l = 0; l < layers.length; l++) { var layer = layers[l]; if (params.layer && layer !== params.layer.id) continue; result.push(util.extend({layer: layer}, geoJSON)); } } callback(null, result); }; function geometryContainsPoint(rings, type, p, radius) { return type === 'Point' ? pointContainsPoint(rings, p, radius) : type === 'LineString' ? lineContainsPoint(rings, p, radius) : type === 'Polygon' ? polyContainsPoint(rings, p) || lineContainsPoint(rings, p, radius) : false; } // Code from http://stackoverflow.com/a/1501725/331379. function distToSegmentSquared(p, v, w) { var l2 = v.distSqr(w); if (l2 === 0) return p.distSqr(v); var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; if (t < 0) return p.distSqr(v); if (t > 1) return p.distSqr(w); return p.distSqr(w.sub(v)._mult(t)._add(v)); } function lineContainsPoint(rings, p, radius) { var r = radius * radius; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 1; j < ring.length; j++) { // Find line segments that have a distance <= radius^2 to p // In that case, we treat the line as "containing point p". var v = ring[j - 1], w = ring[j]; if (distToSegmentSquared(p, v, w) < r) return true; } } return false; } // point in polygon ray casting algorithm function polyContainsPoint(rings, p) { var c = false, ring, p1, p2; for (var k = 0; k < rings.length; k++) { ring = rings[k]; for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { p1 = ring[i]; p2 = ring[j]; if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { c = !c; } } } return c; } function pointContainsPoint(rings, p, radius) { var r = radius * radius; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 0; j < ring.length; j++) { if (ring[j].distSqr(p) <= r) return true; } } return false; } },{"../util/util":96,"point-geometry":113,"rbush":114,"vector-tile":117}],14:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./element_groups'); module.exports = FillBucket; function FillBucket(buffers) { this.buffers = buffers; this.elementGroups = new ElementGroups(buffers.fillVertex, buffers.fillElement, buffers.outlineElement); } FillBucket.prototype.addFeatures = function() { var features = this.features; for (var i = 0; i < features.length; i++) { var feature = features[i]; this.addFeature(feature.loadGeometry()); } }; FillBucket.prototype.addFeature = function(lines) { for (var i = 0; i < lines.length; i++) { this.addFill(lines[i]); } }; FillBucket.prototype.addFill = function(vertices) { if (vertices.length < 3) { //console.warn('a fill must have at least three vertices'); return; } // Calculate the total number of vertices we're going to produce so that we // can resize the buffer beforehand, or detect whether the current line // won't fit into the buffer anymore. // In order to be able to use the vertex buffer for drawing the antialiased // outlines, we separate all polygon vertices with a degenerate (out-of- // viewplane) vertex. var len = vertices.length; // Check whether this geometry buffer can hold all the required vertices. this.elementGroups.makeRoomFor(len + 1); var elementGroup = this.elementGroups.current; var fillVertex = this.buffers.fillVertex; var fillElement = this.buffers.fillElement; var outlineElement = this.buffers.outlineElement; // We're generating triangle fans, so we always start with the first coordinate in this polygon. var firstIndex = fillVertex.index - elementGroup.vertexStartIndex, prevIndex, currentIndex, currentVertex; for (var i = 0; i < vertices.length; i++) { currentIndex = fillVertex.index - elementGroup.vertexStartIndex; currentVertex = vertices[i]; fillVertex.add(currentVertex.x, currentVertex.y); elementGroup.vertexLength++; // Only add triangles that have distinct vertices. if (i >= 2 && (currentVertex.x !== vertices[0].x || currentVertex.y !== vertices[0].y)) { fillElement.add(firstIndex, prevIndex, currentIndex); elementGroup.elementLength++; } if (i >= 1) { outlineElement.add(prevIndex, currentIndex); elementGroup.secondElementLength++; } prevIndex = currentIndex; } }; },{"./element_groups":12}],15:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./element_groups'); module.exports = LineBucket; function LineBucket(buffers, layoutProperties) { this.buffers = buffers; this.elementGroups = new ElementGroups(buffers.lineVertex, buffers.lineElement); this.layoutProperties = layoutProperties; } LineBucket.prototype.addFeatures = function() { var features = this.features; for (var i = 0; i < features.length; i++) { var feature = features[i]; this.addFeature(feature.loadGeometry()); } }; LineBucket.prototype.addFeature = function(lines) { var layoutProperties = this.layoutProperties; for (var i = 0; i < lines.length; i++) { this.addLine(lines[i], layoutProperties['line-join'], layoutProperties['line-cap'], layoutProperties['line-miter-limit'], layoutProperties['line-round-limit']); } }; LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLimit) { var len = vertices.length; // If the line has duplicate vertices at the end, adjust length to remove them. while (len > 2 && vertices[len - 1].equals(vertices[len - 2])) { len--; } if (vertices.length < 2) { //console.warn('a line must have at least two vertices'); return; } if (join === 'bevel') miterLimit = 1.05; var firstVertex = vertices[0], lastVertex = vertices[len - 1], closed = firstVertex.equals(lastVertex); // we could be more precise, but it would only save a negligible amount of space this.elementGroups.makeRoomFor(len * 4); if (len === 2 && closed) { // console.warn('a line may not have coincident points'); return; } var beginCap = cap, endCap = closed ? 'butt' : cap, flip = 1, distance = 0, startOfLine = true, currentVertex, prevVertex, nextVertex, prevNormal, nextNormal, offsetA, offsetB; // the last three vertices added this.e1 = this.e2 = this.e3 = -1; if (closed) { currentVertex = vertices[len - 2]; nextNormal = firstVertex.sub(currentVertex)._unit()._perp(); } for (var i = 0; i < len; i++) { nextVertex = closed && i === len - 1 ? vertices[1] : // if the line is closed, we treat the last vertex like the first vertices[i + 1]; // just the next vertex // if two consecutive vertices exist, skip the current one if (nextVertex && vertices[i].equals(nextVertex)) continue; if (nextNormal) prevNormal = nextNormal; if (currentVertex) prevVertex = currentVertex; currentVertex = vertices[i]; // Calculate how far along the line the currentVertex is if (prevVertex) distance += currentVertex.dist(prevVertex); // Calculate the normal towards the next vertex in this line. In case // there is no next vertex, pretend that the line is continuing straight, // meaning that we are just using the previous normal. nextNormal = nextVertex ? nextVertex.sub(currentVertex)._unit()._perp() : prevNormal; // If we still don't have a previous normal, this is the beginning of a // non-closed line, so we're doing a straight "join". prevNormal = prevNormal || nextNormal; // Determine the normal of the join extrusion. It is the angle bisector // of the segments between the previous line and the next line. var joinNormal = prevNormal.add(nextNormal)._unit(); /* joinNormal prevNormal * ↖ ↑ * .________. prevVertex * | * nextNormal ← | currentVertex * | * nextVertex ! * */ // Calculate the length of the miter (the ratio of the miter to the width). // Find the cosine of the angle between the next and join normals // using dot product. The inverse of that is the miter length. var cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y; var miterLength = 1 / cosHalfAngle; // The join if a middle vertex, otherwise the cap. var middleVertex = prevVertex && nextVertex; var currentJoin = middleVertex ? join : nextVertex ? beginCap : endCap; if (middleVertex && currentJoin === 'round' && miterLength < roundLimit) { currentJoin = 'miter'; } if (currentJoin === 'miter' && miterLength > miterLimit) { currentJoin = 'bevel'; } if (currentJoin === 'bevel') { // The maximum extrude length is 128 / 63 = 2 times the width of the line // so if miterLength >= 2 we need to draw a different type of bevel where. if (miterLength > 2) currentJoin = 'flipbevel'; // If the miterLength is really small and the line bevel wouldn't be visible, // just draw a miter join to save a triangle. if (miterLength < miterLimit) currentJoin = 'miter'; } if (currentJoin === 'miter') { joinNormal._mult(miterLength); this.addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false); } else if (currentJoin === 'flipbevel') { // miter is too big, flip the direction to make a beveled join if (miterLength > 100) { // Almost parallel lines joinNormal = nextNormal.clone(); } else { var direction = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x > 0 ? -1 : 1; var bevelLength = miterLength * prevNormal.add(nextNormal).mag() / prevNormal.sub(nextNormal).mag(); joinNormal._perp()._mult(bevelLength * direction); } this.addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false); flip = -flip; } else if (currentJoin === 'bevel') { var dir = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x; var offset = -Math.sqrt(miterLength * miterLength - 1); if (flip * dir > 0) { offsetB = 0; offsetA = offset; } else { offsetA = 0; offsetB = offset; } // Close previous segment with a bevel if (!startOfLine) { this.addCurrentVertex(currentVertex, flip, distance, prevNormal, offsetA, offsetB, false); } // Start next segment if (nextVertex) { this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -offsetA, -offsetB, false); } } else if (currentJoin === 'butt') { if (!startOfLine) { // Close previous segment with a butt this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 0, 0, false); } // Start next segment with a butt if (nextVertex) { this.addCurrentVertex(currentVertex, flip, distance, nextNormal, 0, 0, false); } } else if (currentJoin === 'square') { if (!startOfLine) { // Close previous segment with a square cap this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 1, 1, false); // The segment is done. Unset vertices to disconnect segments. this.e1 = this.e2 = -1; flip = 1; } // Start next segment if (nextVertex) { this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -1, -1, false); } } else if (currentJoin === 'round') { if (!startOfLine) { // Close previous segment with butt this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 0, 0, false); // Add round cap or linejoin at end of segment this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 1, 1, true); // The segment is done. Unset vertices to disconnect segments. this.e1 = this.e2 = -1; flip = 1; } else if (beginCap === 'round') { // Add round cap before first segment this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -1, -1, true); } // Start next segment with a butt if (nextVertex) { this.addCurrentVertex(currentVertex, flip, distance, nextNormal, 0, 0, false); } } startOfLine = false; } }; /** * Add two vertices to the buffers. * * @param {Object} currentVertex the line vertex to add buffer vertices for * @param {Number} flip -1 if the vertices should be flipped, 1 otherwise * @param {Number} distance the distance from the beggining of the line to the vertex * @param {Number} endLeft extrude to shift the left vertex along the line * @param {Number} endRight extrude to shift the left vertex along the line * @param {Boolean} round whether this is a round cap */ LineBucket.prototype.addCurrentVertex = function(currentVertex, flip, distance, normal, endLeft, endRight, round) { var tx = round ? 1 : 0; var extrude; var lineVertex = this.buffers.lineVertex; var lineElement = this.buffers.lineElement; var elementGroup = this.elementGroups.current; var vertexStartIndex = this.elementGroups.current.vertexStartIndex; extrude = normal.mult(flip); if (endLeft) extrude._sub(normal.perp()._mult(endLeft)); this.e3 = lineVertex.add(currentVertex, extrude, tx, 0, distance) - vertexStartIndex; if (this.e1 >= 0 && this.e2 >= 0) { lineElement.add(this.e1, this.e2, this.e3); elementGroup.elementLength++; } this.e1 = this.e2; this.e2 = this.e3; extrude = normal.mult(-flip); if (endRight) extrude._sub(normal.perp()._mult(endRight)); this.e3 = lineVertex.add(currentVertex, extrude, tx, 1, distance) - vertexStartIndex; if (this.e1 >= 0 && this.e2 >= 0) { lineElement.add(this.e1, this.e2, this.e3); elementGroup.elementLength++; } this.e1 = this.e2; this.e2 = this.e3; elementGroup.vertexLength += 2; }; },{"./element_groups":12}],16:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./element_groups'); var Anchor = require('../symbol/anchor'); var getAnchors = require('../symbol/get_anchors'); var resolveTokens = require('../util/token'); var Quads = require('../symbol/quads'); var Shaping = require('../symbol/shaping'); var resolveText = require('../symbol/resolve_text'); var resolveIcons = require('../symbol/resolve_icons'); var mergeLines = require('../symbol/mergelines'); var shapeText = Shaping.shapeText; var shapeIcon = Shaping.shapeIcon; var getGlyphQuads = Quads.getGlyphQuads; var getIconQuads = Quads.getIconQuads; var clipLine = require('../symbol/clip_line'); var Point = require('point-geometry'); var CollisionFeature = require('../symbol/collision_feature'); module.exports = SymbolBucket; function SymbolBucket(buffers, layoutProperties, collision, overscaling, collisionDebug) { this.buffers = buffers; this.layoutProperties = layoutProperties; this.collision = collision; this.overscaling = overscaling; this.collisionDebug = collisionDebug; this.symbolInstances = []; } SymbolBucket.prototype.addFeatures = function() { var layout = this.layoutProperties; var features = this.features; var textFeatures = this.textFeatures; var horizontalAlign = 0.5, verticalAlign = 0.5; switch (layout['text-anchor']) { case 'right': case 'top-right': case 'bottom-right': horizontalAlign = 1; break; case 'left': case 'top-left': case 'bottom-left': horizontalAlign = 0; break; } switch (layout['text-anchor']) { case 'bottom': case 'bottom-right': case 'bottom-left': verticalAlign = 1; break; case 'top': case 'top-right': case 'top-left': verticalAlign = 0; break; } var justify = layout['text-justify'] === 'right' ? 1 : layout['text-justify'] === 'left' ? 0 : 0.5; var oneEm = 24; var lineHeight = layout['text-line-height'] * oneEm; var maxWidth = layout['symbol-placement'] !== 'line' ? layout['text-max-width'] * oneEm : 0; var spacing = layout['text-letter-spacing'] * oneEm; var textOffset = [layout['text-offset'][0] * oneEm, layout['text-offset'][1] * oneEm]; var fontstack = layout['text-font']; var geometries = []; for (var g = 0; g < features.length; g++) { geometries.push(features[g].loadGeometry()); } if (layout['symbol-placement'] === 'line') { // Merge adjacent lines with the same text to improve labelling. // It's better to place labels on one long line than on many short segments. var merged = mergeLines(features, textFeatures, geometries); geometries = merged.geometries; features = merged.features; textFeatures = merged.textFeatures; } var shapedText, shapedIcon; for (var k = 0; k < features.length; k++) { if (!geometries[k]) continue; if (textFeatures[k]) { shapedText = shapeText(textFeatures[k], this.stacks[fontstack], maxWidth, lineHeight, horizontalAlign, verticalAlign, justify, spacing, textOffset); } else { shapedText = null; } if (layout['icon-image']) { var iconName = resolveTokens(features[k].properties, layout['icon-image']); var image = this.icons[iconName]; shapedIcon = shapeIcon(image, layout); if (image) { if (this.sdfIcons === undefined) { this.sdfIcons = image.sdf; } else if (this.sdfIcons !== image.sdf) { console.warn('Style sheet warning: Cannot mix SDF and non-SDF icons in one bucket'); } } } else { shapedIcon = null; } if (shapedText || shapedIcon) { this.addFeature(geometries[k], shapedText, shapedIcon); } } this.placeFeatures(this.buffers, this.collisionDebug); }; SymbolBucket.prototype.addFeature = function(lines, shapedText, shapedIcon) { var layout = this.layoutProperties; var collision = this.collision; var glyphSize = 24; var fontScale = layout['text-max-size'] / glyphSize, textBoxScale = collision.tilePixelRatio * fontScale, iconBoxScale = collision.tilePixelRatio * layout['icon-max-size'], symbolMinDistance = collision.tilePixelRatio * layout['symbol-min-distance'], avoidEdges = layout['symbol-avoid-edges'], textPadding = layout['text-padding'] * collision.tilePixelRatio, iconPadding = layout['icon-padding'] * collision.tilePixelRatio, textMaxAngle = layout['text-max-angle'] / 180 * Math.PI, textAlongLine = layout['text-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line', iconAlongLine = layout['icon-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line', mayOverlap = layout['text-allow-overlap'] || layout['icon-allow-overlap'] || layout['text-ignore-placement'] || layout['icon-ignore-placement']; if (layout['symbol-placement'] === 'line') { lines = clipLine(lines, 0, 0, 4096, 4096); } for (var i = 0; i < lines.length; i++) { var line = lines[i]; // Calculate the anchor points around which you want to place labels var anchors = layout['symbol-placement'] === 'line' ? getAnchors(line, symbolMinDistance, textMaxAngle, shapedText, glyphSize, textBoxScale, this.overscaling) : [ new Anchor(line[0].x, line[0].y, 0) ]; // For each potential label, create the placement features used to check for collisions, and the quads use for rendering. for (var j = 0, len = anchors.length; j < len; j++) { var anchor = anchors[j]; var inside = !(anchor.x < 0 || anchor.x > 4096 || anchor.y < 0 || anchor.y > 4096); if (avoidEdges && !inside) continue; // Normally symbol layers are drawn across tile boundaries. Only symbols // with their anchors within the tile boundaries are added to the buffers // to prevent symbols from being drawn twice. // // Symbols in layers with overlap are sorted in the y direction so that // symbols lower on the canvas are drawn on top of symbols near the top. // To preserve this order across tile boundaries these symbols can't // be drawn across tile boundaries. Instead they need to be included in // the buffers for both tiles and clipped to tile boundaries at draw time. var addToBuffers = inside || mayOverlap; this.symbolInstances.push(new SymbolInstance(anchor, line, shapedText, shapedIcon, layout, addToBuffers, textBoxScale, textPadding, textAlongLine, iconBoxScale, iconPadding, iconAlongLine)); } } }; SymbolBucket.prototype.placeFeatures = function(buffers, collisionDebug) { // Calculate which labels can be shown and when they can be shown and // create the bufers used for rendering. this.buffers = buffers; var elementGroups = this.elementGroups = { text: new ElementGroups(buffers.glyphVertex, buffers.glyphElement), icon: new ElementGroups(buffers.iconVertex, buffers.iconElement), sdfIcons: this.sdfIcons }; var layout = this.layoutProperties; var collision = this.collision; var maxScale = this.collision.maxScale; var textAlongLine = layout['text-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line'; var iconAlongLine = layout['icon-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line'; var mayOverlap = layout['text-allow-overlap'] || layout['icon-allow-overlap'] || layout['text-ignore-placement'] || layout['icon-ignore-placement']; // Sort symbols by their y position on the canvas so that they lower symbols // are drawn on top of higher symbols. // Don't sort symbols that won't overlap because it isn't necessary and // because it causes more labels to pop in and out when rotating. if (mayOverlap) { var angle = this.collision.angle; var sin = Math.sin(angle), cos = Math.cos(angle); this.symbolInstances.sort(function(a, b) { var aRotated = sin * a.x + cos * a.y; var bRotated = sin * b.x + cos * b.y; return bRotated - aRotated; }); } for (var p = 0; p < this.symbolInstances.length; p++) { var symbolInstance = this.symbolInstances[p]; var hasText = symbolInstance.hasText; var hasIcon = symbolInstance.hasIcon; var iconWithoutText = layout['text-optional'] || !hasText, textWithoutIcon = layout['icon-optional'] || !hasIcon; // Calculate the scales at which the text and icon can be placed without collision. var glyphScale = hasText && !layout['text-allow-overlap'] ? collision.placeFeature(symbolInstance.textCollisionFeature) : collision.minScale; var iconScale = hasIcon && !layout['icon-allow-overlap'] ? collision.placeFeature(symbolInstance.iconCollisionFeature) : collision.minScale; // Combine the scales for icons and text. if (!iconWithoutText && !textWithoutIcon) { iconScale = glyphScale = Math.max(iconScale, glyphScale); } else if (!textWithoutIcon && glyphScale) { glyphScale = Math.max(iconScale, glyphScale); } else if (!iconWithoutText && iconScale) { iconScale = Math.max(iconScale, glyphScale); } // Insert final placement into collision tree and add glyphs/icons to buffers if (hasText) { if (!layout['text-ignore-placement']) { collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale); } if (glyphScale <= maxScale) { this.addSymbols(buffers.glyphVertex, buffers.glyphElement, elementGroups.text, symbolInstance.glyphQuads, glyphScale, layout['text-keep-upright'], textAlongLine); } } if (hasIcon) { if (!layout['icon-ignore-placement']) { collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale); } if (iconScale <= maxScale) { this.addSymbols(buffers.iconVertex, buffers.iconElement, elementGroups.icon, symbolInstance.iconQuads, iconScale, layout['icon-keep-upright'], iconAlongLine); } } } if (collisionDebug) this.addToDebugBuffers(); }; SymbolBucket.prototype.addSymbols = function(vertex, element, elementGroups, quads, scale, keepUpright, alongLine) { elementGroups.makeRoomFor(4 * quads.length); var elementGroup = elementGroups.current; var zoom = this.collision.zoom; var placementZoom = Math.max(Math.log(scale) / Math.LN2 + zoom, 0); var placementAngle = this.collision.angle + Math.PI; for (var k = 0; k < quads.length; k++) { var symbol = quads[k], angle = symbol.angle; // drop upside down versions of glyphs var a = (angle + placementAngle) % (Math.PI * 2); if (keepUpright && alongLine && (a <= Math.PI / 2 || a > Math.PI * 3 / 2)) continue; var tl = symbol.tl, tr = symbol.tr, bl = symbol.bl, br = symbol.br, tex = symbol.tex, anchor = symbol.anchor, minZoom = Math.max(zoom + Math.log(symbol.minScale) / Math.LN2, placementZoom), maxZoom = Math.min(zoom + Math.log(symbol.maxScale) / Math.LN2, 25); if (maxZoom <= minZoom) continue; // Lower min zoom so that while fading out the label it can be shown outside of collision-free zoom levels if (minZoom === placementZoom) minZoom = 0; var triangleIndex = vertex.index - elementGroup.vertexStartIndex; vertex.add(anchor.x, anchor.y, tl.x, tl.y, tex.x, tex.y, minZoom, maxZoom, placementZoom); vertex.add(anchor.x, anchor.y, tr.x, tr.y, tex.x + tex.w, tex.y, minZoom, maxZoom, placementZoom); vertex.add(anchor.x, anchor.y, bl.x, bl.y, tex.x, tex.y + tex.h, minZoom, maxZoom, placementZoom); vertex.add(anchor.x, anchor.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, minZoom, maxZoom, placementZoom); elementGroup.vertexLength += 4; element.add(triangleIndex, triangleIndex + 1, triangleIndex + 2); element.add(triangleIndex + 1, triangleIndex + 2, triangleIndex + 3); elementGroup.elementLength += 2; } }; SymbolBucket.prototype.getDependencies = function(tile, actor, callback) { var firstdone = false; this.getTextDependencies(tile, actor, done); this.getIconDependencies(tile, actor, done); function done(err) { if (err || firstdone) return callback(err); firstdone = true; } }; SymbolBucket.prototype.getIconDependencies = function(tile, actor, callback) { if (this.layoutProperties['icon-image']) { var features = this.features; var icons = resolveIcons(features, this.layoutProperties); if (icons.length) { actor.send('get icons', { icons: icons }, setIcons.bind(this)); } else { callback(); } } else { callback(); } function setIcons(err, newicons) { if (err) return callback(err); this.icons = newicons; callback(); } }; SymbolBucket.prototype.getTextDependencies = function(tile, actor, callback) { var features = this.features; var fontstack = this.layoutProperties['text-font']; var stacks = this.stacks = tile.stacks; if (stacks[fontstack] === undefined) { stacks[fontstack] = {}; } var stack = stacks[fontstack]; var data = resolveText(features, this.layoutProperties, stack); this.textFeatures = data.textFeatures; actor.send('get glyphs', { uid: tile.uid, fontstack: fontstack, codepoints: data.codepoints }, function(err, newstack) { if (err) return callback(err); for (var codepoint in newstack) { stack[codepoint] = newstack[codepoint]; } callback(); }); }; SymbolBucket.prototype.addToDebugBuffers = function() { this.elementGroups.collisionBox = new ElementGroups(this.buffers.collisionBoxVertex); this.elementGroups.collisionBox.makeRoomFor(0); var buffer = this.buffers.collisionBoxVertex; var angle = -this.collision.angle; var yStretch = this.collision.yStretch; for (var j = 0; j < this.symbolInstances.length; j++) { for (var i = 0; i < 2; i++) { var feature = this.symbolInstances[j][i === 0 ? 'textCollisionFeature' : 'iconCollisionFeature']; if (!feature) continue; var boxes = feature.boxes; for (var b = 0; b < boxes.length; b++) { var box = boxes[b]; var anchor = box.anchor; var tl = new Point(box.x1, box.y1 * yStretch)._rotate(angle); var tr = new Point(box.x2, box.y1 * yStretch)._rotate(angle); var bl = new Point(box.x1, box.y2 * yStretch)._rotate(angle); var br = new Point(box.x2, box.y2 * yStretch)._rotate(angle); var maxZoom = Math.max(0, Math.min(25, this.collision.zoom + Math.log(box.maxScale) / Math.LN2)); var placementZoom = Math.max(0, Math.min(25, this.collision.zoom + Math.log(box.placementScale) / Math.LN2)); buffer.add(anchor, tl, maxZoom, placementZoom); buffer.add(anchor, tr, maxZoom, placementZoom); buffer.add(anchor, tr, maxZoom, placementZoom); buffer.add(anchor, br, maxZoom, placementZoom); buffer.add(anchor, br, maxZoom, placementZoom); buffer.add(anchor, bl, maxZoom, placementZoom); buffer.add(anchor, bl, maxZoom, placementZoom); buffer.add(anchor, tl, maxZoom, placementZoom); this.elementGroups.collisionBox.current.vertexLength += 8; } } } }; function SymbolInstance(anchor, line, shapedText, shapedIcon, layout, addToBuffers, textBoxScale, textPadding, textAlongLine, iconBoxScale, iconPadding, iconAlongLine) { this.x = anchor.x; this.y = anchor.y; this.hasText = !!shapedText; this.hasIcon = !!shapedIcon; if (this.hasText) { this.glyphQuads = addToBuffers ? getGlyphQuads(anchor, shapedText, textBoxScale, line, layout, textAlongLine) : []; this.textCollisionFeature = new CollisionFeature(line, anchor, shapedText, textBoxScale, textPadding, textAlongLine); } if (this.hasIcon) { this.iconQuads = addToBuffers ? getIconQuads(anchor, shapedIcon, iconBoxScale, line, layout, iconAlongLine) : []; this.iconCollisionFeature = new CollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine); } } },{"../symbol/anchor":58,"../symbol/clip_line":61,"../symbol/collision_feature":63,"../symbol/get_anchors":65,"../symbol/mergelines":68,"../symbol/quads":69,"../symbol/resolve_icons":70,"../symbol/resolve_text":71,"../symbol/shaping":72,"../util/token":95,"./element_groups":12,"point-geometry":113}],17:[function(require,module,exports){ 'use strict'; module.exports = Coordinate; /** * A coordinate is a column, row, zoom combination, often used * as the data component of a tile. * * @param {Number} column * @param {Number} row * @param {Number} zoom * @private */ function Coordinate(column, row, zoom) { this.column = column; this.row = row; this.zoom = zoom; } Coordinate.prototype = { /** * Create a clone of this coordinate that can be mutated without * changing the original coordinate * * @returns {Coordinate} clone * @private * var coord = new Coordinate(0, 0, 0); * var c2 = coord.clone(); * // since coord is cloned, modifying a property of c2 does * // not modify it. * c2.zoom = 2; */ clone: function() { return new Coordinate(this.column, this.row, this.zoom); }, /** * Zoom this coordinate to a given zoom level. This returns a new * coordinate object, not mutating the old one. * * @param {Number} zoom * @returns {Coordinate} zoomed coordinate * @private * @example * var coord = new Coordinate(0, 0, 0); * var c2 = coord.zoomTo(1); * c2 // equals new Coordinate(0, 0, 1); */ zoomTo: function(zoom) { return this.clone()._zoomTo(zoom); }, /** * Subtract the column and row values of this coordinate from those * of another coordinate. The other coordinat will be zoomed to the * same level as `this` before the subtraction occurs * * @param {Coordinate} c other coordinate * @returns {Coordinate} result * @private */ sub: function(c) { return this.clone()._sub(c); }, _zoomTo: function(zoom) { var scale = Math.pow(2, zoom - this.zoom); this.column *= scale; this.row *= scale; this.zoom = zoom; return this; }, _sub: function(c) { c = c.zoomTo(this.zoom); this.column -= c.column; this.row -= c.row; return this; } }; },{}],18:[function(require,module,exports){ 'use strict'; module.exports = LatLng; var wrap = require('../util/util').wrap; /** * Create a latitude, longitude object from a given latitude and longitude pair in degrees. * * @class LatLng * @classdesc A representation of a latitude and longitude point, in degrees. * @param {number} lat latitude * @param {number} lng longitude * @example * var latlng = new mapboxgl.LatLng(37.76, -122.44); */ function LatLng(lat, lng) { if (isNaN(lat) || isNaN(lng)) { throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); } this.lat = +lat; this.lng = +lng; } /** * Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180). * * @returns {LatLng} wrapped LatLng object * @example * var point = mapboxgl.LatLng(0, 200); * var wrapped = point.wrap(); * wrapped.lng; // = -160 */ LatLng.prototype.wrap = function () { return new LatLng(this.lat, wrap(this.lng, -180, 180)); }; /** * Convert an array to a `LatLng` object, or return an existing `LatLng` object * unchanged. * * @param {Array<number>|LatLng} input `input` to convert * @returns {LatLng} LatLng object or original input * @example * var ll = mapboxgl.LatLng.convert([10, 10]); * var ll2 = new mapboxgl.LatLng(10, 10); * ll // = ll2 */ LatLng.convert = function (input) { if (input instanceof LatLng) { return input; } if (Array.isArray(input)) { return new LatLng(input[0], input[1]); } return input; }; },{"../util/util":96}],19:[function(require,module,exports){ 'use strict'; module.exports = LatLngBounds; var LatLng = require('./lat_lng'); /** * Creates a bounding box from the given pair of points. If parameteres are omitted, a `null` bounding box is created. * * @class LatLngBounds * @classdesc A representation of rectangular box on the earth, defined by its southwest and northeast points in latitude and longitude. * @param {LatLng} sw southwest * @param {LatLng} ne northeast * @example * var sw = new mapboxgl.LatLng(0, 0); * var ne = new mapboxgl.LatLng(10, -10); * var bounds = new mapboxgl.LatLngBounds(sw, ne); * */ function LatLngBounds(sw, ne) { if (!sw) return; var latlngs = ne ? [sw, ne] : sw; for (var i = 0, len = latlngs.length; i < len; i++) { this.extend(latlngs[i]); } } LatLngBounds.prototype = { /** * Extend the bounds to include a given LatLng or LatLngBounds. * * @param {LatLng|LatLngBounds} obj object to extend to * @returns {LatLngBounds} `this` */ extend: function(obj) { var sw = this._sw, ne = this._ne, sw2, ne2; if (obj instanceof LatLng) { sw2 = obj; ne2 = obj; } else if (obj instanceof LatLngBounds) { sw2 = obj._sw; ne2 = obj._ne; if (!sw2 || !ne2) return this; } else { return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this; } if (!sw && !ne) { this._sw = new LatLng(sw2.lat, sw2.lng); this._ne = new LatLng(ne2.lat, ne2.lng); } else { sw.lat = Math.min(sw2.lat, sw.lat); sw.lng = Math.min(sw2.lng, sw.lng); ne.lat = Math.max(ne2.lat, ne.lat); ne.lng = Math.max(ne2.lng, ne.lng); } return this; }, /** * Get the point equidistant from this box's corners * @returns {LatLng} centerpoint * @example * var bounds = new mapboxgl.LatLngBounds( * new mapboxgl.LatLng(10, 10), * new mapboxgl.LatLng(-10, -10); * bounds.getCenter(); // equals mapboxgl.LatLng(0, 0) */ getCenter: function() { return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2); }, /** * Get southwest corner * @returns {LatLng} southwest */ getSouthWest: function() { return this._sw; }, /** * Get northeast corner * @returns {LatLng} northeast */ getNorthEast: function() { return this._ne; }, /** * Get northwest corner * @returns {LatLng} northwest */ getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); }, /** * Get southeast corner * @returns {LatLng} southeast */ getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); }, /** * Get west edge longitude * @returns {number} west */ getWest: function() { return this._sw.lng; }, /** * Get south edge latitude * @returns {number} south */ getSouth: function() { return this._sw.lat; }, /** * Get east edge longitude * @returns {number} east */ getEast: function() { return this._ne.lng; }, /** * Get north edge latitude * @returns {number} north */ getNorth: function() { return this._ne.lat; } }; /** * constructs LatLngBounds from an array if necessary * @param {LatLngBounds|*} a any input * @returns {LatLngBounds|false} * @example * // calls LatLng.convert internally to * // support arrays as latlng values * LatLngBounds.convert([[-10, -10], [10, 10]]); */ LatLngBounds.convert = function (a) { if (!a || a instanceof LatLngBounds) return a; return new LatLngBounds(a); }; },{"./lat_lng":18}],20:[function(require,module,exports){ 'use strict'; var LatLng = require('./lat_lng'), Point = require('point-geometry'), Coordinate = require('./coordinate'), wrap = require('../util/util').wrap, interp = require('../util/interpolate'), vec4 = require('gl-matrix').vec4, mat4 = require('gl-matrix').mat4; module.exports = Transform; /* * A single transform, generally used for a single tile to be * scaled, rotated, and zoomed. * * @param {Number} minZoom * @param {Number} maxZoom * @private */ function Transform(minZoom, maxZoom) { this.tileSize = 512; // constant this._minZoom = minZoom || 0; this._maxZoom = maxZoom || 22; this.latRange = [-85.05113, 85.05113]; this.width = 0; this.height = 0; this.zoom = 0; this.center = new LatLng(0, 0); this.angle = 0; this._altitude = 1.5; this._pitch = 0; } Transform.prototype = { get minZoom() { return this._minZoom; }, set minZoom(zoom) { this._minZoom = zoom; this.zoom = Math.max(this.zoom, zoom); }, get maxZoom() { return this._maxZoom; }, set maxZoom(zoom) { this._maxZoom = zoom; this.zoom = Math.min(this.zoom, zoom); }, get worldSize() { return this.tileSize * this.scale; }, get centerPoint() { return this.size._div(2); }, get size() { return new Point(this.width, this.height); }, get bearing() { return -this.angle / Math.PI * 180; }, set bearing(bearing) { this.angle = -wrap(bearing, -180, 180) * Math.PI / 180; }, get pitch() { return this._pitch / Math.PI * 180; }, set pitch(pitch) { this._pitch = Math.min(60, pitch) / 180 * Math.PI; }, get altitude() { return this._altitude; }, set altitude(altitude) { this._altitude = Math.max(0.75, altitude); }, get zoom() { return this._zoom; }, set zoom(zoom) { zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom); this._zoom = zoom; this.scale = this.zoomScale(zoom); this.tileZoom = Math.floor(zoom); this.zoomFraction = zoom - this.tileZoom; this._constrain(); }, zoomScale: function(zoom) { return Math.pow(2, zoom); }, scaleZoom: function(scale) { return Math.log(scale) / Math.LN2; }, project: function(latlng, worldSize) { return new Point( this.lngX(latlng.lng, worldSize), this.latY(latlng.lat, worldSize)); }, unproject: function(point, worldSize) { return new LatLng( this.yLat(point.y, worldSize), this.xLng(point.x, worldSize)); }, get x() { return this.lngX(this.center.lng); }, get y() { return this.latY(this.center.lat); }, get point() { return new Point(this.x, this.y); }, /** * lat/lon <-> absolute pixel coords conversion * @param {Number} lon * @param {Number} [worldSize=this.worldSize] * @returns {Number} pixel coordinate * @private */ lngX: function(lon, worldSize) { return (180 + lon) * (worldSize || this.worldSize) / 360; }, /** * latitude to absolute y coord * * @param {Number} lat * @param {Number} [worldSize=this.worldSize] * @returns {Number} pixel coordinate * @private */ latY: function(lat, worldSize) { var y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360)); return (180 - y) * (worldSize || this.worldSize) / 360; }, xLng: function(x, worldSize) { return x * 360 / (worldSize || this.worldSize) - 180; }, yLat: function(y, worldSize) { var y2 = 180 - y * 360 / (worldSize || this.worldSize); return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90; }, panBy: function(offset) { var point = this.centerPoint._add(offset); this.center = this.pointLocation(point); this._constrain(); }, setLocationAtPoint: function(latlng, point) { var c = this.locationCoordinate(latlng); var coordAtPoint = this.pointCoordinate(point); var coordCenter = this.pointCoordinate(this.centerPoint); var translate = coordAtPoint._sub(c); this.center = this.coordinateLocation(coordCenter._sub(translate)); this._constrain(); }, setZoomAround: function(zoom, center) { var p = this.locationPoint(center); this.zoom = zoom; this.setLocationAtPoint(center, p); }, setBearingAround: function(bearing, center) { var p = this.locationPoint(center); this.bearing = bearing; this.setLocationAtPoint(center, p); }, /** * Given a location, return the screen point that corresponds to it * @param {LatLng} latlng location * @returns {Point} screen point */ locationPoint: function(latlng) { return this.coordinatePoint(this.locationCoordinate(latlng)); }, /** * Given a point on screen, return its latlng * @param {Point} p screen point * @returns {LatLng} latlng location */ pointLocation: function(p) { return this.coordinateLocation(this.pointCoordinate(p)); }, /** * Given a geographical latlng, return an unrounded * coordinate that represents it at this transform's zoom level and * worldsize. * @param {LatLng} latlng * @returns {Coordinate} */ locationCoordinate: function(latlng) { var k = this.zoomScale(this.tileZoom) / this.worldSize; return new Coordinate( this.lngX(latlng.lng) * k, this.latY(latlng.lat) * k, this.tileZoom); }, /** * Given a Coordinate, return its geographical position. * @param {Coordinate} coord * @returns {LatLng} latlng */ coordinateLocation: function(coord) { var worldSize = this.zoomScale(coord.zoom); return new LatLng( this.yLat(coord.row, worldSize), this.xLng(coord.column, worldSize)); }, pointCoordinate: function(p, targetZ) { if (targetZ === undefined) targetZ = 0; var matrix = this.coordinatePointMatrix(this.tileZoom); var inverted = mat4.invert(new Float64Array(16), matrix); if (!inverted) throw "failed to invert matrix"; // since we don't know the correct projected z value for the point, // unproject two points to get a line and then find the point on that // line with z=0 var coord0 = vec4.transformMat4([], [p.x, p.y, 0, 1], inverted); var coord1 = vec4.transformMat4([], [p.x, p.y, 1, 1], inverted); var w0 = coord0[3]; var w1 = coord1[3]; var x0 = coord0[0] / w0; var x1 = coord1[0] / w1; var y0 = coord0[1] / w0; var y1 = coord1[1] / w1; var z0 = coord0[2] / w0; var z1 = coord1[2] / w1; var t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0); return new Coordinate( interp(x0, x1, t), interp(y0, y1, t), this.tileZoom); }, /** * Given a coordinate, return the screen point that corresponds to it * @param {Coordinate} coord * @returns {Point} screen point */ coordinatePoint: function(coord) { var matrix = this.coordinatePointMatrix(coord.zoom); var p = vec4.transformMat4([], [coord.column, coord.row, 0, 1], matrix); return new Point(p[0] / p[3], p[1] / p[3]); }, coordinatePointMatrix: function(z) { var proj = this.getProjMatrix(); var scale = this.worldSize / this.zoomScale(z); mat4.scale(proj, proj, [scale, scale, 1]); mat4.multiply(proj, this.getPixelMatrix(), proj); return proj; }, /** * converts gl coordinates -1..1 to pixels 0..width * @returns {Object} matrix */ getPixelMatrix: function() { var m = mat4.create(); mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]); mat4.translate(m, m, [1, -1, 0]); return m; }, _constrain: function() { if (!this.center) return; var minY, maxY, minX, maxX, sy, sx, x2, y2, size = this.size; if (this.latRange) { minY = this.latY(this.latRange[1]); maxY = this.latY(this.latRange[0]); sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; } if (this.lngRange) { minX = this.lngX(this.lngRange[0]); maxX = this.lngX(this.lngRange[1]); sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; } // how much the map should scale to fit the screen into given latitude/longitude ranges var s = Math.max(sx || 0, sy || 0); if (s) { this.center = this.unproject(new Point( sx ? (maxX + minX) / 2 : this.x, sy ? (maxY + minY) / 2 : this.y)); this.zoom += this.scaleZoom(s); return; } if (this.latRange) { var y = this.y, h2 = size.y / 2; if (y - h2 < minY) y2 = minY + h2; if (y + h2 > maxY) y2 = maxY - h2; } if (this.lngRange) { var x = this.x, w2 = size.x / 2; if (x - w2 < minX) x2 = minX + w2; if (x + w2 > maxX) x2 = maxX - w2; } // pan the map if the screen goes off the range if (x2 !== undefined || y2 !== undefined) { this.center = this.unproject(new Point( x2 !== undefined ? x2 : this.x, y2 !== undefined ? y2 : this.y)); } }, getProjMatrix: function() { var m = new Float64Array(16); // Find the distance from the center point to the center top in altitude units using law of sines. var halfFov = Math.atan(0.5 / this.altitude); var topHalfSurfaceDistance = Math.sin(halfFov) * this.altitude / Math.sin(Math.PI / 2 - this._pitch - halfFov); // Calculate z value of the farthest fragment that should be rendered. var farZ = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistance + this.altitude; mat4.perspective(m, 2 * Math.atan((this.height / 2) / this.altitude), this.width / this.height, 0.1, farZ); mat4.translate(m, m, [0, 0, -this.altitude]); // After the rotateX, z values are in pixel units. Convert them to // altitude unites. 1 altitude unit = the screen height. mat4.scale(m, m, [1, -1, 1 / this.height]); mat4.rotateX(m, m, this._pitch); mat4.rotateZ(m, m, this.angle); mat4.translate(m, m, [-this.x, -this.y, 0]); return m; } }; },{"../util/interpolate":92,"../util/util":96,"./coordinate":17,"./lat_lng":18,"gl-matrix":104,"point-geometry":113}],21:[function(require,module,exports){ 'use strict'; // Font data From Hershey Simplex Font // http://paulbourke.net/dataformats/hershey/ var simplexFont = { " ": [16, []], "!": [10, [5, 21, 5, 7, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], "\"": [16, [4, 21, 4, 14, -1, -1, 12, 21, 12, 14]], "#": [21, [11, 25, 4, -7, -1, -1, 17, 25, 10, -7, -1, -1, 4, 12, 18, 12, -1, -1, 3, 6, 17, 6]], "$": [20, [8, 25, 8, -4, -1, -1, 12, 25, 12, -4, -1, -1, 17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]], "%": [24, [21, 21, 3, 0, -1, -1, 8, 21, 10, 19, 10, 17, 9, 15, 7, 14, 5, 14, 3, 16, 3, 18, 4, 20, 6, 21, 8, 21, 10, 20, 13, 19, 16, 19, 19, 20, 21, 21, -1, -1, 17, 7, 15, 6, 14, 4, 14, 2, 16, 0, 18, 0, 20, 1, 21, 3, 21, 5, 19, 7, 17, 7]], "&": [26, [23, 12, 23, 13, 22, 14, 21, 14, 20, 13, 19, 11, 17, 6, 15, 3, 13, 1, 11, 0, 7, 0, 5, 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9, 12, 13, 13, 14, 14, 16, 14, 18, 13, 20, 11, 21, 9, 20, 8, 18, 8, 16, 9, 13, 11, 10, 16, 3, 18, 1, 20, 0, 22, 0, 23, 1, 23, 2]], "'": [10, [5, 19, 4, 20, 5, 21, 6, 20, 6, 18, 5, 16, 4, 15]], "(": [14, [11, 25, 9, 23, 7, 20, 5, 16, 4, 11, 4, 7, 5, 2, 7, -2, 9, -5, 11, -7]], ")": [14, [3, 25, 5, 23, 7, 20, 9, 16, 10, 11, 10, 7, 9, 2, 7, -2, 5, -5, 3, -7]], "*": [16, [8, 21, 8, 9, -1, -1, 3, 18, 13, 12, -1, -1, 13, 18, 3, 12]], "+": [26, [13, 18, 13, 0, -1, -1, 4, 9, 22, 9]], ",": [10, [6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]], "-": [26, [4, 9, 22, 9]], ".": [10, [5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], "/": [22, [20, 25, 2, -7]], "0": [20, [9, 21, 6, 20, 4, 17, 3, 12, 3, 9, 4, 4, 6, 1, 9, 0, 11, 0, 14, 1, 16, 4, 17, 9, 17, 12, 16, 17, 14, 20, 11, 21, 9, 21]], "1": [20, [6, 17, 8, 18, 11, 21, 11, 0]], "2": [20, [4, 16, 4, 17, 5, 19, 6, 20, 8, 21, 12, 21, 14, 20, 15, 19, 16, 17, 16, 15, 15, 13, 13, 10, 3, 0, 17, 0]], "3": [20, [5, 21, 16, 21, 10, 13, 13, 13, 15, 12, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]], "4": [20, [13, 21, 3, 7, 18, 7, -1, -1, 13, 21, 13, 0]], "5": [20, [15, 21, 5, 21, 4, 12, 5, 13, 8, 14, 11, 14, 14, 13, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]], "6": [20, [16, 18, 15, 20, 12, 21, 10, 21, 7, 20, 5, 17, 4, 12, 4, 7, 5, 3, 7, 1, 10, 0, 11, 0, 14, 1, 16, 3, 17, 6, 17, 7, 16, 10, 14, 12, 11, 13, 10, 13, 7, 12, 5, 10, 4, 7]], "7": [20, [17, 21, 7, 0, -1, -1, 3, 21, 17, 21]], "8": [20, [8, 21, 5, 20, 4, 18, 4, 16, 5, 14, 7, 13, 11, 12, 14, 11, 16, 9, 17, 7, 17, 4, 16, 2, 15, 1, 12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6, 11, 9, 12, 13, 13, 15, 14, 16, 16, 16, 18, 15, 20, 12, 21, 8, 21]], "9": [20, [16, 14, 15, 11, 13, 9, 10, 8, 9, 8, 6, 9, 4, 11, 3, 14, 3, 15, 4, 18, 6, 20, 9, 21, 10, 21, 13, 20, 15, 18, 16, 14, 16, 9, 15, 4, 13, 1, 10, 0, 8, 0, 5, 1, 4, 3]], ":": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], ";": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]], "<": [24, [20, 18, 4, 9, 20, 0]], "=": [26, [4, 12, 22, 12, -1, -1, 4, 6, 22, 6]], ">": [24, [4, 18, 20, 9, 4, 0]], "?": [18, [3, 16, 3, 17, 4, 19, 5, 20, 7, 21, 11, 21, 13, 20, 14, 19, 15, 17, 15, 15, 14, 13, 13, 12, 9, 10, 9, 7, -1, -1, 9, 2, 8, 1, 9, 0, 10, 1, 9, 2]], "@": [27, [18, 13, 17, 15, 15, 16, 12, 16, 10, 15, 9, 14, 8, 11, 8, 8, 9, 6, 11, 5, 14, 5, 16, 6, 17, 8, -1, -1, 12, 16, 10, 14, 9, 11, 9, 8, 10, 6, 11, 5, -1, -1, 18, 16, 17, 8, 17, 6, 19, 5, 21, 5, 23, 7, 24, 10, 24, 12, 23, 15, 22, 17, 20, 19, 18, 20, 15, 21, 12, 21, 9, 20, 7, 19, 5, 17, 4, 15, 3, 12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1, 12, 0, 15, 0, 18, 1, 20, 2, 21, 3, -1, -1, 19, 16, 18, 8, 18, 6, 19, 5]], "A": [18, [9, 21, 1, 0, -1, -1, 9, 21, 17, 0, -1, -1, 4, 7, 14, 7]], "B": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, -1, -1, 4, 11, 13, 11, 16, 10, 17, 9, 18, 7, 18, 4, 17, 2, 16, 1, 13, 0, 4, 0]], "C": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5]], "D": [21, [4, 21, 4, 0, -1, -1, 4, 21, 11, 21, 14, 20, 16, 18, 17, 16, 18, 13, 18, 8, 17, 5, 16, 3, 14, 1, 11, 0, 4, 0]], "E": [19, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11, -1, -1, 4, 0, 17, 0]], "F": [18, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11]], "G": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 18, 8, -1, -1, 13, 8, 18, 8]], "H": [22, [4, 21, 4, 0, -1, -1, 18, 21, 18, 0, -1, -1, 4, 11, 18, 11]], "I": [8, [4, 21, 4, 0]], "J": [16, [12, 21, 12, 5, 11, 2, 10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7]], "K": [21, [4, 21, 4, 0, -1, -1, 18, 21, 4, 7, -1, -1, 9, 12, 18, 0]], "L": [17, [4, 21, 4, 0, -1, -1, 4, 0, 16, 0]], "M": [24, [4, 21, 4, 0, -1, -1, 4, 21, 12, 0, -1, -1, 20, 21, 12, 0, -1, -1, 20, 21, 20, 0]], "N": [22, [4, 21, 4, 0, -1, -1, 4, 21, 18, 0, -1, -1, 18, 21, 18, 0]], "O": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21]], "P": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 14, 17, 12, 16, 11, 13, 10, 4, 10]], "Q": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, -1, -1, 12, 4, 18, -2]], "R": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, 4, 11, -1, -1, 11, 11, 18, 0]], "S": [20, [17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]], "T": [16, [8, 21, 8, 0, -1, -1, 1, 21, 15, 21]], "U": [22, [4, 21, 4, 6, 5, 3, 7, 1, 10, 0, 12, 0, 15, 1, 17, 3, 18, 6, 18, 21]], "V": [18, [1, 21, 9, 0, -1, -1, 17, 21, 9, 0]], "W": [24, [2, 21, 7, 0, -1, -1, 12, 21, 7, 0, -1, -1, 12, 21, 17, 0, -1, -1, 22, 21, 17, 0]], "X": [20, [3, 21, 17, 0, -1, -1, 17, 21, 3, 0]], "Y": [18, [1, 21, 9, 11, 9, 0, -1, -1, 17, 21, 9, 11]], "Z": [20, [17, 21, 3, 0, -1, -1, 3, 21, 17, 21, -1, -1, 3, 0, 17, 0]], "[": [14, [4, 25, 4, -7, -1, -1, 5, 25, 5, -7, -1, -1, 4, 25, 11, 25, -1, -1, 4, -7, 11, -7]], "\\": [14, [0, 21, 14, -3]], "]": [14, [9, 25, 9, -7, -1, -1, 10, 25, 10, -7, -1, -1, 3, 25, 10, 25, -1, -1, 3, -7, 10, -7]], "^": [16, [6, 15, 8, 18, 10, 15, -1, -1, 3, 12, 8, 17, 13, 12, -1, -1, 8, 17, 8, 0]], "_": [16, [0, -2, 16, -2]], "`": [10, [6, 21, 5, 20, 4, 18, 4, 16, 5, 15, 6, 16, 5, 17]], "a": [19, [15, 14, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "b": [19, [4, 21, 4, 0, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]], "c": [18, [15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "d": [19, [15, 21, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "e": [18, [3, 8, 15, 8, 15, 10, 14, 12, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "f": [12, [10, 21, 8, 21, 6, 20, 5, 17, 5, 0, -1, -1, 2, 14, 9, 14]], "g": [19, [15, 14, 15, -2, 14, -5, 13, -6, 11, -7, 8, -7, 6, -6, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "h": [19, [4, 21, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]], "i": [8, [3, 21, 4, 20, 5, 21, 4, 22, 3, 21, -1, -1, 4, 14, 4, 0]], "j": [10, [5, 21, 6, 20, 7, 21, 6, 22, 5, 21, -1, -1, 6, 14, 6, -3, 5, -6, 3, -7, 1, -7]], "k": [17, [4, 21, 4, 0, -1, -1, 14, 14, 4, 4, -1, -1, 8, 8, 15, 0]], "l": [8, [4, 21, 4, 0]], "m": [30, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, 15, 10, 18, 13, 20, 14, 23, 14, 25, 13, 26, 10, 26, 0]], "n": [19, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]], "o": [19, [8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, 16, 6, 16, 8, 15, 11, 13, 13, 11, 14, 8, 14]], "p": [19, [4, 14, 4, -7, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]], "q": [19, [15, 14, 15, -7, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "r": [13, [4, 14, 4, 0, -1, -1, 4, 8, 5, 11, 7, 13, 9, 14, 12, 14]], "s": [17, [14, 11, 13, 13, 10, 14, 7, 14, 4, 13, 3, 11, 4, 9, 6, 8, 11, 7, 13, 6, 14, 4, 14, 3, 13, 1, 10, 0, 7, 0, 4, 1, 3, 3]], "t": [12, [5, 21, 5, 4, 6, 1, 8, 0, 10, 0, -1, -1, 2, 14, 9, 14]], "u": [19, [4, 14, 4, 4, 5, 1, 7, 0, 10, 0, 12, 1, 15, 4, -1, -1, 15, 14, 15, 0]], "v": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0]], "w": [22, [3, 14, 7, 0, -1, -1, 11, 14, 7, 0, -1, -1, 11, 14, 15, 0, -1, -1, 19, 14, 15, 0]], "x": [17, [3, 14, 14, 0, -1, -1, 14, 14, 3, 0]], "y": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0, 6, -4, 4, -6, 2, -7, 1, -7]], "z": [17, [14, 14, 3, 0, -1, -1, 3, 14, 14, 14, -1, -1, 3, 0, 14, 0]], "{": [14, [9, 25, 7, 24, 6, 23, 5, 21, 5, 19, 6, 17, 7, 16, 8, 14, 8, 12, 6, 10, -1, -1, 7, 24, 6, 22, 6, 20, 7, 18, 8, 17, 9, 15, 9, 13, 8, 11, 4, 9, 8, 7, 9, 5, 9, 3, 8, 1, 7, 0, 6, -2, 6, -4, 7, -6, -1, -1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, -1, 5, -3, 6, -5, 7, -6, 9, -7]], "|": [8, [4, 25, 4, -7]], "}": [14, [5, 25, 7, 24, 8, 23, 9, 21, 9, 19, 8, 17, 7, 16, 6, 14, 6, 12, 8, 10, -1, -1, 7, 24, 8, 22, 8, 20, 7, 18, 6, 17, 5, 15, 5, 13, 6, 11, 10, 9, 6, 7, 5, 5, 5, 3, 6, 1, 7, 0, 8, -2, 8, -4, 7, -6, -1, -1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, -1, 9, -3, 8, -5, 7, -6, 5, -7]], "~": [24, [3, 6, 3, 8, 4, 11, 6, 12, 8, 12, 10, 11, 14, 8, 16, 7, 18, 7, 20, 8, 21, 10, -1, -1, 3, 8, 4, 10, 6, 11, 8, 11, 10, 10, 14, 7, 16, 6, 18, 6, 20, 7, 21, 10, 21, 12]] }; module.exports = function textVertices(text, left, baseline, scale) { scale = scale || 1; var strokes = [], i, len, j, len2, glyph, x, y, prev; for (i = 0, len = text.length; i < len; i++) { glyph = simplexFont[text[i]]; if (!glyph) continue; prev = null; for (j = 0, len2 = glyph[1].length; j < len2; j += 2) { if (glyph[1][j] === -1 && glyph[1][j + 1] === -1) { prev = null; } else { x = left + glyph[1][j] * scale; y = baseline - glyph[1][j + 1] * scale; if (prev) { strokes.push(prev.x, prev.y, x, y); } prev = {x: x, y: y}; } } left += glyph[0] * scale; } return strokes; }; },{}],22:[function(require,module,exports){ 'use strict'; /** * mapboxgl is a A WebGL JavaScript interactive maps library that can render * [Mapbox vector tiles](https://www.mapbox.com/blog/vector-tiles/). * * @module mapboxgl * @summary WebGL JavaScript map library */ // jshint -W079 var mapboxgl = module.exports = {}; mapboxgl.Map = require('./ui/map'); mapboxgl.Navigation = require('./ui/control/navigation'); mapboxgl.Attribution = require('./ui/control/attribution'); mapboxgl.Popup = require('./ui/popup'); mapboxgl.GeoJSONSource = require('./source/geojson_source'); mapboxgl.VideoSource = require('./source/video_source'); mapboxgl.Style = require('./style/style'); mapboxgl.LatLng = require('./geo/lat_lng'); mapboxgl.LatLngBounds = require('./geo/lat_lng_bounds'); mapboxgl.Point = require('point-geometry'); mapboxgl.Evented = require('./util/evented'); mapboxgl.util = require('./util/util'); mapboxgl.supported = require('./util/browser').supported; var ajax = require('./util/ajax'); mapboxgl.util.getJSON = ajax.getJSON; mapboxgl.util.getArrayBuffer = ajax.getArrayBuffer; var config = require('./util/config'); mapboxgl.config = config; Object.defineProperty(mapboxgl, 'accessToken', { get: function() { return config.ACCESS_TOKEN; }, set: function(token) { config.ACCESS_TOKEN = token; } }); },{"./geo/lat_lng":18,"./geo/lat_lng_bounds":19,"./source/geojson_source":36,"./source/video_source":44,"./style/style":52,"./ui/control/attribution":75,"./ui/control/navigation":77,"./ui/map":81,"./ui/popup":82,"./util/ajax":84,"./util/browser":85,"./util/config":89,"./util/evented":90,"./util/util":96,"point-geometry":113}],23:[function(require,module,exports){ 'use strict'; var mat3 = require('gl-matrix').mat3; module.exports = drawBackground; function drawBackground(painter, layer, posMatrix) { var gl = painter.gl; var color = layer.paint['background-color']; var image = layer.paint['background-image']; var opacity = layer.paint['background-opacity']; var shader; var imagePosA = image ? painter.spriteAtlas.getPosition(image.from, true) : null; var imagePosB = image ? painter.spriteAtlas.getPosition(image.to, true) : null; if (imagePosA && imagePosB) { // Draw texture fill shader = painter.patternShader; gl.switchShader(shader, posMatrix); gl.uniform1i(shader.u_image, 0); gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl); gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br); gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl); gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br); gl.uniform1f(shader.u_opacity, opacity); var transform = painter.transform; var sizeA = imagePosA.size; var sizeB = imagePosB.size; var center = transform.locationCoordinate(transform.center); var scale = 1 / Math.pow(2, transform.zoomFraction); gl.uniform1f(shader.u_mix, image.t); var matrixA = mat3.create(); mat3.scale(matrixA, matrixA, [ 1 / (sizeA[0] * image.fromScale), 1 / (sizeA[1] * image.fromScale) ]); mat3.translate(matrixA, matrixA, [ (center.column * transform.tileSize) % (sizeA[0] * image.fromScale), (center.row * transform.tileSize) % (sizeA[1] * image.fromScale) ]); mat3.rotate(matrixA, matrixA, -transform.angle); mat3.scale(matrixA, matrixA, [ scale * transform.width / 2, -scale * transform.height / 2 ]); var matrixB = mat3.create(); mat3.scale(matrixB, matrixB, [ 1 / (sizeB[0] * image.toScale), 1 / (sizeB[1] * image.toScale) ]); mat3.translate(matrixB, matrixB, [ (center.column * transform.tileSize) % (sizeB[0] * image.toScale), (center.row * transform.tileSize) % (sizeB[1] * image.toScale) ]); mat3.rotate(matrixB, matrixB, -transform.angle); mat3.scale(matrixB, matrixB, [ scale * transform.width / 2, -scale * transform.height / 2 ]); gl.uniformMatrix3fv(shader.u_patternmatrix_a, false, matrixA); gl.uniformMatrix3fv(shader.u_patternmatrix_b, false, matrixB); painter.spriteAtlas.bind(gl, true); } else { // Draw filling rectangle. shader = painter.fillShader; gl.switchShader(shader, posMatrix); gl.uniform4fv(shader.u_color, color); } gl.disable(gl.STENCIL_TEST); gl.bindBuffer(gl.ARRAY_BUFFER, painter.backgroundBuffer); gl.vertexAttribPointer(shader.a_pos, painter.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.backgroundBuffer.itemCount); gl.enable(gl.STENCIL_TEST); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } },{"gl-matrix":104}],24:[function(require,module,exports){ 'use strict'; module.exports = drawPlacementDebug; function drawPlacementDebug(painter, layer, posMatrix, tile) { var elementGroups = tile.elementGroups[layer.ref || layer.id].collisionBox; if (!elementGroups) return; var gl = painter.gl; var buffer = tile.buffers.collisionBoxVertex; var shader = painter.collisionBoxShader; gl.enable(gl.STENCIL_TEST); gl.switchShader(shader, posMatrix); buffer.bind(gl, shader); gl.lineWidth(3); var stride = 12; gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, 0); gl.vertexAttribPointer(shader.a_extrude, 2, gl.SHORT, false, stride, 4); gl.vertexAttribPointer(shader.a_data, 2, gl.UNSIGNED_BYTE, false, stride, 8); gl.uniform1f(shader.u_scale, Math.pow(2, painter.transform.zoom - tile.coord.z)); gl.uniform1f(shader.u_zoom, painter.transform.zoom * 10); gl.uniform1f(shader.u_maxzoom, (tile.coord.z + 1) * 10); var begin = elementGroups.groups[0].vertexStartIndex; var len = elementGroups.groups[0].vertexLength; gl.drawArrays(gl.LINES, begin, len); gl.disable(gl.STENCIL_TEST); } },{}],25:[function(require,module,exports){ 'use strict'; var textVertices = require('../lib/debugtext'); var browser = require('../util/browser'); module.exports = drawDebug; function drawDebug(painter, tile) { var gl = painter.gl; // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.switchShader(painter.debugShader, tile.posMatrix); // draw bounding rectangle gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugBuffer); gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugBuffer.itemSize, gl.SHORT, false, 0, 0); gl.uniform4f(painter.debugShader.u_color, 1, 0, 0, 1); gl.lineWidth(4); gl.drawArrays(gl.LINE_STRIP, 0, painter.debugBuffer.itemCount); var vertices = textVertices(tile.coord.toString(), 50, 200, 5); gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugTextBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array(vertices), gl.STREAM_DRAW); gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugTextBuffer.itemSize, gl.SHORT, false, 0, 0); gl.lineWidth(8 * browser.devicePixelRatio); gl.uniform4f(painter.debugShader.u_color, 1, 1, 1, 1); gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize); gl.lineWidth(2 * browser.devicePixelRatio); gl.uniform4f(painter.debugShader.u_color, 0, 0, 0, 1); gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize); // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); } },{"../lib/debugtext":21,"../util/browser":85}],26:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser'); var mat3 = require('gl-matrix').mat3; module.exports = drawFill; function drawFill(painter, layer, posMatrix, tile) { // No data if (!tile.buffers) return; var elementGroups = tile.elementGroups[layer.ref || layer.id]; if (!elementGroups) return; var gl = painter.gl; var translatedPosMatrix = painter.translateMatrix(posMatrix, tile, layer.paint['fill-translate'], layer.paint['fill-translate-anchor']); var color = layer.paint['fill-color']; var vertex, elements, group, count; // Draw the stencil mask. // We're only drawing to the first seven bits (== support a maximum of // 127 overlapping polygons in one place before we get rendering errors). gl.stencilMask(0x3F); gl.clear(gl.STENCIL_BUFFER_BIT); // Draw front facing triangles. Wherever the 0x80 bit is 1, we are // increasing the lower 7 bits by one if the triangle is a front-facing // triangle. This means that all visible polygons should be in CCW // orientation, while all holes (see below) are in CW orientation. gl.stencilFunc(gl.NOTEQUAL, 0x80, 0x80); // When we do a nonzero fill, we count the number of times a pixel is // covered by a counterclockwise polygon, and subtract the number of // times it is "uncovered" by a clockwise polygon. gl.stencilOpSeparate(gl.FRONT, gl.INCR_WRAP, gl.KEEP, gl.KEEP); gl.stencilOpSeparate(gl.BACK, gl.DECR_WRAP, gl.KEEP, gl.KEEP); // When drawing a shape, we first draw all shapes to the stencil buffer // and incrementing all areas where polygons are gl.colorMask(false, false, false, false); // Draw the actual triangle fan into the stencil buffer. gl.switchShader(painter.fillShader, translatedPosMatrix); // Draw all buffers vertex = tile.buffers.fillVertex; vertex.bind(gl); elements = tile.buffers.fillElement; elements.bind(gl); var offset, elementOffset; for (var i = 0; i < elementGroups.groups.length; i++) { group = elementGroups.groups[i]; offset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(painter.fillShader.a_pos, 2, gl.SHORT, false, 4, offset + 0); count = group.elementLength * 3; elementOffset = group.elementStartIndex * elements.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } // Now that we have the stencil mask in the stencil buffer, we can start // writing to the color buffer. gl.colorMask(true, true, true, true); // From now on, we don't want to update the stencil buffer anymore. gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); gl.stencilMask(0x0); var strokeColor = layer.paint['fill-outline-color']; // Because we're drawing top-to-bottom, and we update the stencil mask // below, we have to draw the outline first (!) if (layer.paint['fill-antialias'] === true && !(layer.paint['fill-image'] && !strokeColor)) { gl.switchShader(painter.outlineShader, translatedPosMatrix); gl.lineWidth(2 * browser.devicePixelRatio); if (strokeColor) { // If we defined a different color for the fill outline, we are // going to ignore the bits in 0x3F and just care about the global // clipping mask. gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } else { // Otherwise, we only want to draw the antialiased parts that are // *outside* the current shape. This is important in case the fill // or stroke color is translucent. If we wouldn't clip to outside // the current shape, some pixels from the outline stroke overlapped // the (non-antialiased) fill. gl.stencilFunc(gl.EQUAL, 0x80, 0xBF); } gl.uniform2f(painter.outlineShader.u_world, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.uniform4fv(painter.outlineShader.u_color, strokeColor ? strokeColor : color); // Draw all buffers vertex = tile.buffers.fillVertex; elements = tile.buffers.outlineElement; elements.bind(gl); for (var k = 0; k < elementGroups.groups.length; k++) { group = elementGroups.groups[k]; offset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(painter.outlineShader.a_pos, 2, gl.SHORT, false, 4, offset + 0); count = group.secondElementLength * 2; elementOffset = group.secondElementStartIndex * elements.itemSize; gl.drawElements(gl.LINES, count, gl.UNSIGNED_SHORT, elementOffset); } } var image = layer.paint['fill-image']; var opacity = layer.paint['fill-opacity'] || 1; var shader; if (image) { // Draw texture fill var imagePosA = painter.spriteAtlas.getPosition(image.from, true); var imagePosB = painter.spriteAtlas.getPosition(image.to, true); if (!imagePosA || !imagePosB) return; shader = painter.patternShader; gl.switchShader(shader, posMatrix); gl.uniform1i(shader.u_image, 0); gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl); gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br); gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl); gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br); gl.uniform1f(shader.u_opacity, opacity); gl.uniform1f(shader.u_mix, image.t); var factor = (tile.tileExtent / tile.tileSize) / Math.pow(2, painter.transform.tileZoom - tile.coord.z); var matrixA = mat3.create(); mat3.scale(matrixA, matrixA, [ 1 / (imagePosA.size[0] * factor * image.fromScale), 1 / (imagePosA.size[1] * factor * image.fromScale) ]); var matrixB = mat3.create(); mat3.scale(matrixB, matrixB, [ 1 / (imagePosB.size[0] * factor * image.toScale), 1 / (imagePosB.size[1] * factor * image.toScale) ]); gl.uniformMatrix3fv(shader.u_patternmatrix_a, false, matrixA); gl.uniformMatrix3fv(shader.u_patternmatrix_b, false, matrixB); painter.spriteAtlas.bind(gl, true); } else { // Draw filling rectangle. shader = painter.fillShader; gl.switchShader(shader, posMatrix); gl.uniform4fv(shader.u_color, color); } // Only draw regions that we marked gl.stencilFunc(gl.NOTEQUAL, 0x0, 0x3F); gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer); gl.vertexAttribPointer(shader.a_pos, painter.tileExtentBuffer.itemSize, gl.SHORT, false, 0, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.tileExtentBuffer.itemCount); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } },{"../util/browser":85,"gl-matrix":104}],27:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser'); var mat2 = require('gl-matrix').mat2; /** * Draw a line. Under the hood this will read elements from * a tile, dash textures from a lineAtlas, and style properties from a layer. * @param {Object} painter * @param {Object} layer * @param {Object} posMatrix * @param {Tile} tile * @returns {undefined} draws with the painter */ module.exports = function drawLine(painter, layer, posMatrix, tile) { // No data if (!tile.buffers) return; var elementGroups = tile.elementGroups[layer.ref || layer.id]; if (!elementGroups) return; var gl = painter.gl; // don't draw zero-width lines if (layer.paint['line-width'] <= 0) return; // the distance over which the line edge fades out. // Retina devices need a smaller distance to avoid aliasing. var antialiasing = 1 / browser.devicePixelRatio; var blur = layer.paint['line-blur'] + antialiasing; var edgeWidth = layer.paint['line-width'] / 2; var inset = -1; var offset = 0; var shift = 0; if (layer.paint['line-gap-width'] > 0) { inset = layer.paint['line-gap-width'] / 2 + antialiasing * 0.5; edgeWidth = layer.paint['line-width']; // shift outer lines half a pixel towards the middle to eliminate the crack offset = inset - antialiasing / 2; } var outset = offset + edgeWidth + antialiasing / 2 + shift; var color = layer.paint['line-color']; var ratio = painter.transform.scale / (1 << tile.coord.z) / (tile.tileExtent / tile.tileSize); var vtxMatrix = painter.translateMatrix(posMatrix, tile, layer.paint['line-translate'], layer.paint['line-translate-anchor']); var tr = painter.transform; var antialiasingMatrix = mat2.create(); mat2.scale(antialiasingMatrix, antialiasingMatrix, [1, Math.cos(tr._pitch)]); mat2.rotate(antialiasingMatrix, antialiasingMatrix, painter.transform.angle); // calculate how much longer the real world distance is at the top of the screen // than at the middle of the screen. var topedgelength = Math.sqrt(tr.height * tr.height / 4 * (1 + tr.altitude * tr.altitude)); var x = tr.height / 2 * Math.tan(tr._pitch); var extra = (topedgelength + x) / topedgelength - 1; // how much the tile is overscaled by var overscaling = tile.tileSize / painter.transform.tileSize; var shader; var dasharray = layer.paint['line-dasharray']; var image = layer.paint['line-image']; if (dasharray) { shader = painter.linesdfpatternShader; gl.switchShader(shader, vtxMatrix, tile.exMatrix); gl.uniform2fv(shader.u_linewidth, [ outset, inset ]); gl.uniform1f(shader.u_ratio, ratio); gl.uniform1f(shader.u_blur, blur); gl.uniform4fv(shader.u_color, color); var posA = painter.lineAtlas.getDash(dasharray.from, layer.layout['line-cap'] === 'round'); var posB = painter.lineAtlas.getDash(dasharray.to, layer.layout['line-cap'] === 'round'); painter.lineAtlas.bind(gl); var patternratio = Math.pow(2, Math.floor(Math.log(painter.transform.scale) / Math.LN2) - tile.coord.z) / 8 * overscaling; var scaleA = [patternratio / posA.width / dasharray.fromScale, -posA.height / 2]; var gammaA = painter.lineAtlas.width / (dasharray.fromScale * posA.width * 256 * browser.devicePixelRatio) / 2; var scaleB = [patternratio / posB.width / dasharray.toScale, -posB.height / 2]; var gammaB = painter.lineAtlas.width / (dasharray.toScale * posB.width * 256 * browser.devicePixelRatio) / 2; gl.uniform2fv(shader.u_patternscale_a, scaleA); gl.uniform1f(shader.u_tex_y_a, posA.y); gl.uniform2fv(shader.u_patternscale_b, scaleB); gl.uniform1f(shader.u_tex_y_b, posB.y); gl.uniform1i(shader.u_image, 0); gl.uniform1f(shader.u_sdfgamma, Math.max(gammaA, gammaB)); gl.uniform1f(shader.u_mix, dasharray.t); } else if (image) { var imagePosA = painter.spriteAtlas.getPosition(image.from, true); var imagePosB = painter.spriteAtlas.getPosition(image.to, true); if (!imagePosA || !imagePosB) return; var factor = tile.tileExtent / tile.tileSize / Math.pow(2, painter.transform.tileZoom - tile.coord.z) * overscaling; painter.spriteAtlas.bind(gl, true); shader = painter.linepatternShader; gl.switchShader(shader, vtxMatrix, tile.exMatrix); gl.uniform2fv(shader.u_linewidth, [ outset, inset ]); gl.uniform1f(shader.u_ratio, ratio); gl.uniform1f(shader.u_blur, blur); gl.uniform2fv(shader.u_pattern_size_a, [imagePosA.size[0] * factor * image.fromScale, imagePosB.size[1] ]); gl.uniform2fv(shader.u_pattern_size_b, [imagePosB.size[0] * factor * image.toScale, imagePosB.size[1] ]); gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl); gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br); gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl); gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br); gl.uniform1f(shader.u_fade, image.t); gl.uniform1f(shader.u_opacity, layer.paint['line-opacity']); } else { shader = painter.lineShader; gl.switchShader(shader, vtxMatrix, tile.exMatrix); gl.uniform2fv(shader.u_linewidth, [ outset, inset ]); gl.uniform1f(shader.u_ratio, ratio); gl.uniform1f(shader.u_blur, blur); gl.uniform1f(shader.u_extra, extra); gl.uniformMatrix2fv(shader.u_antialiasingmatrix, false, antialiasingMatrix); gl.uniform4fv(shader.u_color, color); } var vertex = tile.buffers.lineVertex; vertex.bind(gl); var element = tile.buffers.lineElement; element.bind(gl); for (var i = 0; i < elementGroups.groups.length; i++) { var group = elementGroups.groups[i]; var vtxOffset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, vtxOffset + 0); gl.vertexAttribPointer(shader.a_data, 4, gl.BYTE, false, 8, vtxOffset + 4); var count = group.elementLength * 3; var elementOffset = group.elementStartIndex * element.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } }; },{"../util/browser":85,"gl-matrix":104}],28:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); module.exports = drawRaster; function drawRaster(painter, layer, posMatrix, tile) { var gl = painter.gl; gl.disable(gl.STENCIL_TEST); var shader = painter.rasterShader; gl.switchShader(shader, posMatrix); // color parameters gl.uniform1f(shader.u_brightness_low, layer.paint['raster-brightness-min']); gl.uniform1f(shader.u_brightness_high, layer.paint['raster-brightness-max']); gl.uniform1f(shader.u_saturation_factor, saturationFactor(layer.paint['raster-saturation'])); gl.uniform1f(shader.u_contrast_factor, contrastFactor(layer.paint['raster-contrast'])); gl.uniform3fv(shader.u_spin_weights, spinWeights(layer.paint['raster-hue-rotate'])); var parentTile = tile.source && tile.source._pyramid.findLoadedParent(tile.coord, 0, {}), opacities = getOpacities(tile, parentTile, layer, painter.transform); var parentScaleBy, parentTL; gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, tile.texture); if (parentTile) { gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, parentTile.texture); parentScaleBy = Math.pow(2, parentTile.coord.z - tile.coord.z); parentTL = [tile.coord.x * parentScaleBy % 1, tile.coord.y * parentScaleBy % 1]; } else { opacities[1] = 0; } // cross-fade parameters gl.uniform2fv(shader.u_tl_parent, parentTL || [0, 0]); gl.uniform1f(shader.u_scale_parent, parentScaleBy || 1); gl.uniform1f(shader.u_buffer_scale, 1); gl.uniform1f(shader.u_opacity0, opacities[0]); gl.uniform1f(shader.u_opacity1, opacities[1]); gl.uniform1i(shader.u_image0, 0); gl.uniform1i(shader.u_image1, 1); gl.bindBuffer(gl.ARRAY_BUFFER, tile.boundsBuffer || painter.tileExtentBuffer); gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, 0); gl.vertexAttribPointer(shader.a_texture_pos, 2, gl.SHORT, false, 8, 4); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); gl.enable(gl.STENCIL_TEST); } function spinWeights(angle) { angle *= Math.PI / 180; var s = Math.sin(angle); var c = Math.cos(angle); return [ (2 * c + 1) / 3, (-Math.sqrt(3) * s - c + 1) / 3, (Math.sqrt(3) * s - c + 1) / 3 ]; } function contrastFactor(contrast) { return contrast > 0 ? 1 / (1 - contrast) : 1 + contrast; } function saturationFactor(saturation) { return saturation > 0 ? 1 - 1 / (1.001 - saturation) : -saturation; } function getOpacities(tile, parentTile, layer, transform) { if (!tile.source) return [1, 0]; var now = new Date().getTime(); var fadeDuration = layer.paint['raster-fade-duration']; var sinceTile = (now - tile.timeAdded) / fadeDuration; var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1; var idealZ = tile.source._pyramid.coveringZoomLevel(transform); var parentFurther = parentTile ? Math.abs(parentTile.coord.z - idealZ) > Math.abs(tile.coord.z - idealZ) : false; var opacity = []; if (!parentTile || parentFurther) { // if no parent or parent is older opacity[0] = util.clamp(sinceTile, 0, 1); opacity[1] = 1 - opacity[0]; } else { // parent is younger, zooming out opacity[0] = util.clamp(1 - sinceParent, 0, 1); opacity[1] = 1 - opacity[0]; } var op = layer.paint['raster-opacity']; opacity[0] *= op; opacity[1] *= op; return opacity; } },{"../util/util":96}],29:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser'); var mat4 = require('gl-matrix').mat4; var drawCollisionDebug = require('./draw_collision_debug'); module.exports = drawSymbols; function drawSymbols(painter, layer, posMatrix, tile) { // No data if (!tile.buffers) return; var elementGroups = tile.elementGroups[layer.ref || layer.id]; if (!elementGroups) return; var drawAcrossEdges = !(layer.layout['text-allow-overlap'] || layer.layout['icon-allow-overlap'] || layer.layout['text-ignore-placement'] || layer.layout['icon-ignore-placement']); var gl = painter.gl; if (drawAcrossEdges) { // Disable the stencil test so that labels aren't clipped to tile boundaries. // // Layers with features that may be drawn overlapping aren't clipped. These // layers are sorted in the y direction, and to draw the correct ordering near // tile edges the icons are included in both tiles and clipped when drawing. gl.disable(gl.STENCIL_TEST); } if (elementGroups.text.groups.length) { drawSymbol(painter, layer, posMatrix, tile, elementGroups.text, 'text', true); } if (elementGroups.icon.groups.length) { drawSymbol(painter, layer, posMatrix, tile, elementGroups.icon, 'icon', elementGroups.sdfIcons); } drawCollisionDebug(painter, layer, posMatrix, tile); if (drawAcrossEdges) { gl.enable(gl.STENCIL_TEST); } } var defaultSizes = { icon: 1, text: 24 }; function drawSymbol(painter, layer, posMatrix, tile, elementGroups, prefix, sdf) { var gl = painter.gl; posMatrix = painter.translateMatrix(posMatrix, tile, layer.paint[prefix + '-translate'], layer.paint[prefix + '-translate-anchor']); var tr = painter.transform; var alignedWithMap = layer.layout[prefix + '-rotation-alignment'] === 'map'; var skewed = alignedWithMap; var exMatrix, s, gammaScale; if (skewed) { exMatrix = mat4.create(); s = tile.tileExtent / tile.tileSize / Math.pow(2, painter.transform.zoom - tile.coord.z); gammaScale = 1 / Math.cos(tr._pitch); } else { exMatrix = mat4.clone(tile.exMatrix); s = painter.transform.altitude; gammaScale = 1; } mat4.scale(exMatrix, exMatrix, [s, s, 1]); // If layer.paint.size > layer.layout[prefix + '-max-size'] then labels may collide var fontSize = layer.paint[prefix + '-size']; var fontScale = fontSize / defaultSizes[prefix]; mat4.scale(exMatrix, exMatrix, [ fontScale, fontScale, 1 ]); // calculate how much longer the real world distance is at the top of the screen // than at the middle of the screen. var topedgelength = Math.sqrt(tr.height * tr.height / 4 * (1 + tr.altitude * tr.altitude)); var x = tr.height / 2 * Math.tan(tr._pitch); var extra = (topedgelength + x) / topedgelength - 1; var text = prefix === 'text'; var shader, vertex, elements, texsize; if (!text && !painter.style.sprite.loaded()) return; gl.activeTexture(gl.TEXTURE0); if (sdf) { shader = painter.sdfShader; } else { shader = painter.iconShader; } if (text) { painter.glyphAtlas.updateTexture(gl); vertex = tile.buffers.glyphVertex; elements = tile.buffers.glyphElement; texsize = [painter.glyphAtlas.width / 4, painter.glyphAtlas.height / 4]; } else { painter.spriteAtlas.bind(gl, alignedWithMap || painter.options.rotating || painter.options.zooming || fontScale !== 1 || sdf || painter.transform.pitch); vertex = tile.buffers.iconVertex; elements = tile.buffers.iconElement; texsize = [painter.spriteAtlas.width / 4, painter.spriteAtlas.height / 4]; } gl.switchShader(shader, posMatrix, exMatrix); gl.uniform1i(shader.u_texture, 0); gl.uniform2fv(shader.u_texsize, texsize); gl.uniform1i(shader.u_skewed, skewed); gl.uniform1f(shader.u_extra, extra); // adjust min/max zooms for variable font sies var zoomAdjust = Math.log(fontSize / layer.layout[prefix + '-max-size']) / Math.LN2 || 0; gl.uniform1f(shader.u_zoom, (painter.transform.zoom - zoomAdjust) * 10); // current zoom level var f = painter.frameHistory.getFadeProperties(300); gl.uniform1f(shader.u_fadedist, f.fadedist * 10); gl.uniform1f(shader.u_minfadezoom, Math.floor(f.minfadezoom * 10)); gl.uniform1f(shader.u_maxfadezoom, Math.floor(f.maxfadezoom * 10)); gl.uniform1f(shader.u_fadezoom, (painter.transform.zoom + f.bump) * 10); var group, offset, count, elementOffset; elements.bind(gl); if (sdf) { var sdfPx = 8; var blurOffset = 1.19; var haloOffset = 6; var gamma = 0.105 * defaultSizes[prefix] / fontSize / browser.devicePixelRatio; gl.uniform1f(shader.u_gamma, gamma * gammaScale); gl.uniform4fv(shader.u_color, layer.paint[prefix + '-color']); gl.uniform1f(shader.u_buffer, (256 - 64) / 256); for (var i = 0; i < elementGroups.groups.length; i++) { group = elementGroups.groups[i]; offset = group.vertexStartIndex * vertex.itemSize; vertex.bind(gl, shader, offset); count = group.elementLength * 3; elementOffset = group.elementStartIndex * elements.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } if (layer.paint[prefix + '-halo-color']) { // Draw halo underneath the text. gl.uniform1f(shader.u_gamma, (layer.paint[prefix + '-halo-blur'] * blurOffset / fontScale / sdfPx + gamma) * gammaScale); gl.uniform4fv(shader.u_color, layer.paint[prefix + '-halo-color']); gl.uniform1f(shader.u_buffer, (haloOffset - layer.paint[prefix + '-halo-width'] / fontScale) / sdfPx); for (var j = 0; j < elementGroups.groups.length; j++) { group = elementGroups.groups[j]; offset = group.vertexStartIndex * vertex.itemSize; vertex.bind(gl, shader, offset); count = group.elementLength * 3; elementOffset = group.elementStartIndex * elements.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } } } else { gl.uniform1f(shader.u_opacity, layer.paint['icon-opacity']); for (var k = 0; k < elementGroups.groups.length; k++) { group = elementGroups.groups[k]; offset = group.vertexStartIndex * vertex.itemSize; vertex.bind(gl, shader, offset); count = group.elementLength * 3; elementOffset = group.elementStartIndex * elements.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } } } },{"../util/browser":85,"./draw_collision_debug":24,"gl-matrix":104}],30:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser'); var mat4 = require('gl-matrix').mat4; module.exports = drawVertices; function drawVertices(painter, layer, posMatrix, tile) { var gl = painter.gl; if (!tile || !tile.buffers) return; var elementGroups = tile.elementGroups[layer.ref || layer.id]; if (!elementGroups) return; // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); // Draw all buffers if (layer.type === 'fill') { drawPoints(tile.buffers.fillVertex, elementGroups.groups, posMatrix, 4); } else if (layer.type === 'symbol') { drawPoints(tile.buffers.iconVertex, elementGroups.icon.groups, posMatrix, 16); drawPoints(tile.buffers.glyphVertex, elementGroups.text.groups, posMatrix, 16); } else if (layer.type === 'line') { var newPosMatrix = mat4.clone(posMatrix); mat4.scale(newPosMatrix, newPosMatrix, [0.5, 0.5, 1]); drawPoints(tile.buffers.lineVertex, elementGroups.groups, newPosMatrix, 8); } function drawPoints(vertex, groups, matrix, stride) { gl.switchShader(painter.dotShader, matrix); gl.uniform1f(painter.dotShader.u_size, 4 * browser.devicePixelRatio); gl.uniform1f(painter.dotShader.u_blur, 0.25); gl.uniform4fv(painter.dotShader.u_color, [0.1, 0, 0, 0.1]); vertex.bind(gl, painter.dotShader, 0); for (var i = 0; i < groups.length; i++) { var group = groups[i]; var begin = group.vertexStartIndex; var count = group.vertexLength; gl.vertexAttribPointer(painter.dotShader.a_pos, 2, gl.SHORT, false, stride, 0); gl.drawArrays(gl.POINTS, begin, count); } } // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); } },{"../util/browser":85,"gl-matrix":104}],31:[function(require,module,exports){ 'use strict'; module.exports = FrameHistory; function FrameHistory() { this.frameHistory = []; } FrameHistory.prototype.getFadeProperties = function(duration) { if (duration === undefined) duration = 300; var currentTime = (new Date()).getTime(); // Remove frames until only one is outside the duration, or until there are only three while (this.frameHistory.length > 3 && this.frameHistory[1].time + duration < currentTime) { this.frameHistory.shift(); } if (this.frameHistory[1].time + duration < currentTime) { this.frameHistory[0].z = this.frameHistory[1].z; } var frameLen = this.frameHistory.length; if (frameLen < 3) console.warn('there should never be less than three frames in the history'); // Find the range of zoom levels we want to fade between var startingZ = this.frameHistory[0].z, lastFrame = this.frameHistory[frameLen - 1], endingZ = lastFrame.z, lowZ = Math.min(startingZ, endingZ), highZ = Math.max(startingZ, endingZ); // Calculate the speed of zooming, and how far it would zoom in terms of zoom levels in one duration var zoomDiff = lastFrame.z - this.frameHistory[1].z, timeDiff = lastFrame.time - this.frameHistory[1].time; var fadedist = zoomDiff / (timeDiff / duration); if (isNaN(fadedist)) console.warn('fadedist should never be NaN'); // At end of a zoom when the zoom stops changing continue pretending to zoom at that speed // bump is how much farther it would have been if it had continued zooming at the same rate var bump = (currentTime - lastFrame.time) / duration * fadedist; return { fadedist: fadedist, minfadezoom: lowZ, maxfadezoom: highZ, bump: bump }; }; // Record frame history that will be used to calculate fading params FrameHistory.prototype.record = function(zoom) { var currentTime = (new Date()).getTime(); // first frame ever if (!this.frameHistory.length) { this.frameHistory.push({time: 0, z: zoom }, {time: 0, z: zoom }); } if (this.frameHistory.length === 2 || this.frameHistory[this.frameHistory.length - 1].z !== zoom) { this.frameHistory.push({ time: currentTime, z: zoom }); } }; },{}],32:[function(require,module,exports){ 'use strict'; var shaders = require('./shaders'); var util = require('../util/util'); exports.extend = function(context) { var origLineWidth = context.lineWidth, lineWidthRange = context.getParameter(context.ALIASED_LINE_WIDTH_RANGE); context.lineWidth = function(width) { origLineWidth.call(context, util.clamp(width, lineWidthRange[0], lineWidthRange[1])); }; context.getShader = function(name, type) { var kind = type === this.FRAGMENT_SHADER ? 'fragment' : 'vertex'; if (!shaders[name] || !shaders[name][kind]) { throw new Error("Could not find shader " + name); } var shader = this.createShader(type); this.shaderSource(shader, shaders[name][kind]); this.compileShader(shader); if (!this.getShaderParameter(shader, this.COMPILE_STATUS)) { throw new Error(this.getShaderInfoLog(shader)); } return shader; }; context.initializeShader = function(name, attributes, uniforms) { var shader = { program: this.createProgram(), fragment: this.getShader(name, this.FRAGMENT_SHADER), vertex: this.getShader(name, this.VERTEX_SHADER), attributes: [] }; this.attachShader(shader.program, shader.vertex); this.attachShader(shader.program, shader.fragment); this.linkProgram(shader.program); if (!this.getProgramParameter(shader.program, this.LINK_STATUS)) { console.error(this.getProgramInfoLog(shader.program)); } else { for (var i = 0; i < attributes.length; i++) { shader[attributes[i]] = this.getAttribLocation(shader.program, attributes[i]); shader.attributes.push(shader[attributes[i]]); } for (var k = 0; k < uniforms.length; k++) { shader[uniforms[k]] = this.getUniformLocation(shader.program, uniforms[k]); } } return shader; }; // Switches to a different shader program. context.switchShader = function(shader, posMatrix, exMatrix) { if (!posMatrix) { console.trace('posMatrix does not have required argument'); } if (this.currentShader !== shader) { this.useProgram(shader.program); // Disable all attributes from the existing shader that aren't used in // the new shader. Note: attribute indices are *not* program specific! var enabled = this.currentShader ? this.currentShader.attributes : []; var required = shader.attributes; for (var i = 0; i < enabled.length; i++) { if (required.indexOf(enabled[i]) < 0) { this.disableVertexAttribArray(enabled[i]); } } // Enable all attributes for the new shader. for (var j = 0; j < required.length; j++) { if (enabled.indexOf(required[j]) < 0) { this.enableVertexAttribArray(required[j]); } } this.currentShader = shader; } // Update the matrices if necessary. Note: This relies on object identity! // This means changing the matrix values without the actual matrix object // will FAIL to update the matrix properly. if (shader.posMatrix !== posMatrix) { this.uniformMatrix4fv(shader.u_matrix, false, posMatrix); shader.posMatrix = posMatrix; } if (exMatrix && shader.exMatrix !== exMatrix && shader.u_exmatrix) { this.uniformMatrix4fv(shader.u_exmatrix, false, exMatrix); shader.exMatrix = exMatrix; } }; return context; }; },{"../util/util":96,"./shaders":35}],33:[function(require,module,exports){ 'use strict'; module.exports = LineAtlas; /** * Much like a GlyphAtlas, a LineAtlas lets us reuse rendered dashed lines * by writing many of them to a texture and then fetching their positions * using .getDash. * * @param {number} width * @param {number} height * @private */ function LineAtlas(width, height) { this.width = width; this.height = height; this.nextRow = 0; this.bytes = 4; this.data = new Uint8Array(this.width * this.height * this.bytes); this.positions = {}; } LineAtlas.prototype.setSprite = function(sprite) { this.sprite = sprite; }; /** * Get or create a dash line pattern. * * @param {Array<number>} dasharray * @param {boolean} round whether to add circle caps in between dash segments * @returns {Object} position of dash texture in { y, height, width } * @private */ LineAtlas.prototype.getDash = function(dasharray, round) { var key = dasharray.join(",") + round; if (!this.positions[key]) { this.positions[key] = this.addDash(dasharray, round); } return this.positions[key]; }; LineAtlas.prototype.addDash = function(dasharray, round) { var n = round ? 7 : 0; var height = 2 * n + 1; var offset = 128; if (this.nextRow + height > this.height) { console.warn('LineAtlas out of space'); return null; } var length = 0; for (var i = 0; i < dasharray.length; i++) { length += dasharray[i]; } var stretch = this.width / length; var halfWidth = stretch / 2; // If dasharray has an odd length, both the first and last parts // are dashes and should be joined seamlessly. var oddLength = dasharray.length % 2 === 1; for (var y = -n; y <= n; y++) { var row = this.nextRow + n + y; var index = this.width * row; var left = oddLength ? -dasharray[dasharray.length - 1] : 0; var right = dasharray[0]; var partIndex = 1; for (var x = 0; x < this.width; x++) { while (right < x / stretch) { left = right; right = right + dasharray[partIndex]; if (oddLength && partIndex === dasharray.length - 1) { right += dasharray[0]; } partIndex++; } var distLeft = Math.abs(x - left * stretch); var distRight = Math.abs(x - right * stretch); var dist = Math.min(distLeft, distRight); var inside = (partIndex % 2) === 1; var signedDistance; if (round) { // Add circle caps var distMiddle = n ? y / n * (halfWidth + 1) : 0; if (inside) { var distEdge = halfWidth - Math.abs(distMiddle); signedDistance = Math.sqrt(dist * dist + distEdge * distEdge); } else { signedDistance = halfWidth - Math.sqrt(dist * dist + distMiddle * distMiddle); } } else { signedDistance = (inside ? 1 : -1) * dist; } this.data[3 + (index + x) * 4] = Math.max(0, Math.min(255, signedDistance + offset)); } } var pos = { y: (this.nextRow + n + 0.5) / this.height, height: 2 * n / this.height, width: length }; this.nextRow += height; this.dirty = true; return pos; }; LineAtlas.prototype.bind = function(gl) { if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.data); } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); if (this.dirty) { this.dirty = false; gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, this.data); } } }; LineAtlas.prototype.debug = function() { var canvas = document.createElement('canvas'); document.body.appendChild(canvas); canvas.style.position = 'absolute'; canvas.style.top = 0; canvas.style.left = 0; canvas.style.background = '#ff0'; canvas.width = this.width; canvas.height = this.height; var ctx = canvas.getContext('2d'); var data = ctx.getImageData(0, 0, this.width, this.height); for (var i = 0; i < this.data.length; i++) { if (this.sdf) { var k = i * 4; data.data[k] = data.data[k + 1] = data.data[k + 2] = 0; data.data[k + 3] = this.data[i]; } else { data.data[i] = this.data[i]; } } ctx.putImageData(data, 0, 0); }; },{}],34:[function(require,module,exports){ 'use strict'; var glutil = require('./gl_util'); var browser = require('../util/browser'); var mat4 = require('gl-matrix').mat4; var FrameHistory = require('./frame_history'); /* * Initialize a new painter object. * * @param {Canvas} gl an experimental-webgl drawing context */ module.exports = Painter; function Painter(gl, transform) { this.gl = glutil.extend(gl); this.transform = transform; this.reusableTextures = {}; this.preFbos = {}; this.frameHistory = new FrameHistory(); this.setup(); } /* * Update the GL viewport, projection matrix, and transforms to compensate * for a new width and height value. */ Painter.prototype.resize = function(width, height) { var gl = this.gl; this.width = width * browser.devicePixelRatio; this.height = height * browser.devicePixelRatio; gl.viewport(0, 0, this.width, this.height); }; Painter.prototype.setup = function() { var gl = this.gl; gl.verbose = true; // We are blending the new pixels *behind* the existing pixels. That way we can // draw front-to-back and use then stencil buffer to cull opaque pixels early. gl.enable(gl.BLEND); gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); gl.enable(gl.STENCIL_TEST); // Initialize shaders this.debugShader = gl.initializeShader('debug', ['a_pos'], ['u_matrix', 'u_pointsize', 'u_color']); this.gaussianShader = gl.initializeShader('gaussian', ['a_pos'], ['u_matrix', 'u_image', 'u_offset']); this.rasterShader = gl.initializeShader('raster', ['a_pos', 'a_texture_pos'], ['u_matrix', 'u_brightness_low', 'u_brightness_high', 'u_saturation_factor', 'u_spin_weights', 'u_contrast_factor', 'u_opacity0', 'u_opacity1', 'u_image0', 'u_image1', 'u_tl_parent', 'u_scale_parent', 'u_buffer_scale']); this.lineShader = gl.initializeShader('line', ['a_pos', 'a_data'], ['u_matrix', 'u_linewidth', 'u_color', 'u_ratio', 'u_blur', 'u_extra', 'u_antialiasingmatrix']); this.linepatternShader = gl.initializeShader('linepattern', ['a_pos', 'a_data'], ['u_matrix', 'u_exmatrix', 'u_linewidth', 'u_ratio', 'u_pattern_size_a', 'u_pattern_size_b', 'u_pattern_tl_a', 'u_pattern_br_a', 'u_pattern_tl_b', 'u_pattern_br_b', 'u_blur', 'u_fade', 'u_opacity']); this.linesdfpatternShader = gl.initializeShader('linesdfpattern', ['a_pos', 'a_data'], ['u_matrix', 'u_exmatrix', 'u_linewidth', 'u_color', 'u_ratio', 'u_blur', 'u_patternscale_a', 'u_tex_y_a', 'u_patternscale_b', 'u_tex_y_b', 'u_image', 'u_sdfgamma', 'u_mix']); this.dotShader = gl.initializeShader('dot', ['a_pos'], ['u_matrix', 'u_size', 'u_color', 'u_blur']); this.sdfShader = gl.initializeShader('sdf', ['a_pos', 'a_offset', 'a_data1', 'a_data2'], ['u_matrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_color', 'u_gamma', 'u_buffer', 'u_zoom', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom', 'u_skewed', 'u_extra']); this.iconShader = gl.initializeShader('icon', ['a_pos', 'a_offset', 'a_data1', 'a_data2'], ['u_matrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_zoom', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom', 'u_opacity', 'u_skewed', 'u_extra']); this.outlineShader = gl.initializeShader('outline', ['a_pos'], ['u_matrix', 'u_color', 'u_world'] ); this.patternShader = gl.initializeShader('pattern', ['a_pos'], ['u_matrix', 'u_pattern_tl_a', 'u_pattern_br_a', 'u_pattern_tl_b', 'u_pattern_br_b', 'u_mix', 'u_patternmatrix_a', 'u_patternmatrix_b', 'u_opacity', 'u_image'] ); this.fillShader = gl.initializeShader('fill', ['a_pos'], ['u_matrix', 'u_color'] ); this.collisionBoxShader = gl.initializeShader('collisionbox', ['a_pos', 'a_extrude', 'a_data'], ['u_matrix', 'u_scale', 'u_zoom', 'u_maxzoom'] ); this.identityMatrix = mat4.create(); // The backgroundBuffer is used when drawing to the full *canvas* this.backgroundBuffer = gl.createBuffer(); this.backgroundBuffer.itemSize = 2; this.backgroundBuffer.itemCount = 4; gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW); this.setExtent(4096); // The debugTextBuffer is used to draw tile IDs for debugging this.debugTextBuffer = gl.createBuffer(); this.debugTextBuffer.itemSize = 2; }; /** * Rebind the necessary buffers to render at a different extent than * the current one. No-ops if the extent is not changing. * * @param {number} newExtent * @example * this.setExtent(4096); */ Painter.prototype.setExtent = function(newExtent) { if (!newExtent || newExtent === this.tileExtent) return; this.tileExtent = newExtent; var gl = this.gl; // The tileExtentBuffer is used when drawing to a full *tile* this.tileExtentBuffer = gl.createBuffer(); this.tileExtentBuffer.itemSize = 4; this.tileExtentBuffer.itemCount = 4; gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer); gl.bufferData( gl.ARRAY_BUFFER, new Int16Array([ // tile coord x, tile coord y, texture coord x, texture coord y 0, 0, 0, 0, this.tileExtent, 0, 32767, 0, 0, this.tileExtent, 0, 32767, this.tileExtent, this.tileExtent, 32767, 32767 ]), gl.STATIC_DRAW); // The debugBuffer is used to draw tile outlines for debugging this.debugBuffer = gl.createBuffer(); this.debugBuffer.itemSize = 2; this.debugBuffer.itemCount = 5; gl.bindBuffer(gl.ARRAY_BUFFER, this.debugBuffer); gl.bufferData( gl.ARRAY_BUFFER, new Int16Array([ 0, 0, this.tileExtent - 1, 0, this.tileExtent - 1, this.tileExtent - 1, 0, this.tileExtent - 1, 0, 0]), gl.STATIC_DRAW); }; /* * Reset the color buffers of the drawing canvas. */ Painter.prototype.clearColor = function() { var gl = this.gl; gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); }; /* * Reset the drawing canvas by clearing the stencil buffer so that we can draw * new tiles at the same location, while retaining previously drawn pixels. */ Painter.prototype.clearStencil = function() { var gl = this.gl; gl.clearStencil(0x0); gl.stencilMask(0xFF); gl.clear(gl.STENCIL_BUFFER_BIT); }; Painter.prototype.drawClippingMask = function(tile) { var gl = this.gl; gl.switchShader(this.fillShader, tile.posMatrix); gl.colorMask(false, false, false, false); // Clear the entire stencil buffer, except for the 7th bit, which stores // the global clipping mask that allows us to avoid drawing in regions of // tiles we've already painted in. gl.clearStencil(0x0); gl.stencilMask(0xBF); gl.clear(gl.STENCIL_BUFFER_BIT); // The stencil test will fail always, meaning we set all pixels covered // by this geometry to 0x80. We use the highest bit 0x80 to mark the regions // we want to draw in. All pixels that have this bit *not* set will never be // drawn in. gl.stencilFunc(gl.EQUAL, 0xC0, 0x40); gl.stencilMask(0xC0); gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP); // Draw the clipping mask gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer); gl.vertexAttribPointer(this.fillShader.a_pos, this.tileExtentBuffer.itemSize, gl.SHORT, false, 8, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.tileExtentBuffer.itemCount); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); gl.stencilMask(0x00); gl.colorMask(true, true, true, true); }; // Overridden by headless tests. Painter.prototype.prepareBuffers = function() {}; Painter.prototype.bindDefaultFramebuffer = function() { var gl = this.gl; gl.bindFramebuffer(gl.FRAMEBUFFER, null); }; var draw = { symbol: require('./draw_symbol'), line: require('./draw_line'), fill: require('./draw_fill'), raster: require('./draw_raster'), background: require('./draw_background'), debug: require('./draw_debug'), vertices: require('./draw_vertices') }; Painter.prototype.render = function(style, options) { this.style = style; this.options = options; this.lineAtlas = style.lineAtlas; this.spriteAtlas = style.spriteAtlas; this.spriteAtlas.setSprite(style.sprite); this.glyphAtlas = style.glyphAtlas; this.glyphAtlas.bind(this.gl); this.frameHistory.record(this.transform.zoom); this.prepareBuffers(); this.clearColor(); for (var i = style._groups.length - 1; i >= 0; i--) { var group = style._groups[i]; var source = style.sources[group.source]; if (source) { this.clearStencil(); source.render(group, this); } else if (group.source === undefined) { this.drawLayers(group, this.identityMatrix); } } }; Painter.prototype.drawTile = function(tile, layers) { this.setExtent(tile.tileExtent); this.drawClippingMask(tile); this.drawLayers(layers, tile.posMatrix, tile); if (this.options.debug) { draw.debug(this, tile); } }; Painter.prototype.drawLayers = function(layers, matrix, tile) { for (var i = layers.length - 1; i >= 0; i--) { var layer = layers[i]; if (layer.hidden) continue; draw[layer.type](this, layer, matrix, tile); if (this.options.vertices) { draw.vertices(this, layer, matrix, tile); } } }; // Draws non-opaque areas. This is for debugging purposes. Painter.prototype.drawStencilBuffer = function() { var gl = this.gl; gl.switchShader(this.fillShader, this.identityMatrix); // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); // Drw the filling quad where the stencil buffer isn't set. gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer); gl.vertexAttribPointer(this.fillShader.a_pos, this.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0); gl.uniform4fv(this.fillShader.u_color, [0, 0, 0, 0.5]); gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.backgroundBuffer.itemCount); // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); }; Painter.prototype.translateMatrix = function(matrix, tile, translate, anchor) { if (!translate[0] && !translate[1]) return matrix; if (anchor === 'viewport') { var sinA = Math.sin(-this.transform.angle); var cosA = Math.cos(-this.transform.angle); translate = [ translate[0] * cosA - translate[1] * sinA, translate[0] * sinA + translate[1] * cosA ]; } var tilePixelRatio = this.transform.scale / (1 << tile.coord.z) / (tile.tileExtent / tile.tileSize); var translation = [ translate[0] / tilePixelRatio, translate[1] / tilePixelRatio, 0 ]; var translatedMatrix = new Float32Array(16); mat4.translate(translatedMatrix, matrix, translation); return translatedMatrix; }; Painter.prototype.saveTexture = function(texture) { var textures = this.reusableTextures[texture.size]; if (!textures) { this.reusableTextures[texture.size] = [texture]; } else { textures.push(texture); } }; Painter.prototype.getTexture = function(size) { var textures = this.reusableTextures[size]; return textures && textures.length > 0 ? textures.pop() : null; }; },{"../util/browser":85,"./draw_background":23,"./draw_debug":25,"./draw_fill":26,"./draw_line":27,"./draw_raster":28,"./draw_symbol":29,"./draw_vertices":30,"./frame_history":31,"./gl_util":32,"gl-matrix":104}],35:[function(require,module,exports){ 'use strict'; var glify = undefined; module.exports = { "debug": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform float u_pointsize;uniform mat4 u_matrix;void main(){gl_Position=u_matrix*vec4(a_pos,step(32767.,a_pos.x),1);gl_PointSize=u_pointsize;}","fragment":"precision mediump float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"}, "dot": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform float u_size;attribute vec2 a_pos;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);gl_PointSize=u_size;}","fragment":"precision mediump float;uniform vec4 u_color;uniform float u_blur;void main(){float a,b;a=length(gl_PointCoord-.5);b=smoothstep(.5,.5-u_blur,a);gl_FragColor=u_color*b;}"}, "fill": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);gl_PointSize=2.;}","fragment":"precision mediump float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"}, "gaussian": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_offset;varying vec2 a[3];void main(){gl_Position=u_matrix*vec4(a_pos,0,1);vec2 b=gl_Position.xy/2.+.5;a[0]=b;a[1]=b+u_offset*1.1824255238063563;a[2]=b-u_offset*1.1824255238063563;}","fragment":"precision mediump float;uniform sampler2D u_image;varying vec2 a[3];void main(){vec4 b=vec4(0);b+=texture2D(u_image,a[0])*.40261994689424746;b+=texture2D(u_image,a[1])*.2986900265528763;b+=texture2D(u_image,a[2])*.2986900265528763;gl_FragColor=b;}"}, "line": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix;uniform float u_ratio,u_extra;uniform vec2 u_linewidth;uniform vec4 u_color;uniform mat2 u_antialiasingmatrix;varying vec2 a;varying float b,c;void main(){vec2 d,e;d=a_data.xy;e=mod(a_pos,2.);e.y=sign(e.y-.5);a=e;vec4 f=vec4(u_linewidth.s*d*.015873016,0,0);gl_Position=u_matrix*vec4(floor(a_pos*.5)+f.xy/u_ratio,0,1);float g,h,i;g=gl_Position.y/gl_Position.w;h=length(d)/length(u_antialiasingmatrix*d);i=1./(1.-g*u_extra);c=i*h;}","fragment":"precision mediump float;uniform vec2 u_linewidth,u_dasharray;uniform vec4 u_color;uniform float u_blur;varying vec2 a;varying float b,c;void main(){float d,e,f;d=length(a)*u_linewidth.s;e=u_blur*c;f=clamp(min(d-(u_linewidth.t-e),u_linewidth.s-d)/e,0.,1.);gl_FragColor=u_color*f;}"}, "linepattern": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix,u_exmatrix;uniform float u_ratio;uniform vec2 u_linewidth;uniform vec4 u_color;varying vec2 a;varying float b;void main(){vec2 c,e,f,g;c=a_data.xy;float d=a_data.z*128.+a_data.w;e=mod(a_pos,2.);e.y=sign(e.y-.5);a=e;f=c*.015873016;g=u_linewidth.s*f;gl_Position=u_matrix*vec4(floor(a_pos*.5)+g.xy/u_ratio,0,1);b=d;}","fragment":"precision mediump float;uniform vec2 u_linewidth,u_pattern_size_a,u_pattern_size_b,u_pattern_tl_a,u_pattern_br_a,u_pattern_tl_b,u_pattern_br_b;uniform float u_point,u_blur,u_fade,u_opacity;uniform sampler2D u_image;varying vec2 a;varying float b;void main(){float c,d,e,f,g,h;c=length(a)*u_linewidth.s;d=clamp(min(c-(u_linewidth.t-u_blur),u_linewidth.s-c)/u_blur,0.,1.);e=mod(b/u_pattern_size_a.x,1.);f=mod(b/u_pattern_size_b.x,1.);g=.5+a.y*u_linewidth.s/u_pattern_size_a.y;h=.5+a.y*u_linewidth.s/u_pattern_size_b.y;vec2 i,j;i=mix(u_pattern_tl_a,u_pattern_br_a,vec2(e,g));j=mix(u_pattern_tl_b,u_pattern_br_b,vec2(f,h));vec4 k=mix(texture2D(u_image,i),texture2D(u_image,j),u_fade);d*=u_opacity;gl_FragColor=k*d;}"}, "linesdfpattern": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix,u_exmatrix;uniform vec2 u_linewidth,u_patternscale_a,u_patternscale_b;uniform float u_ratio,u_tex_y_a,u_tex_y_b;varying vec2 a,b,c;void main(){vec2 d,f;d=a_data.xy;float e=a_data.z*128.+a_data.w;f=mod(a_pos,2.);f.y=sign(f.y-.5);a=f;vec4 g=vec4(u_linewidth.s*d*.015873016,0,0);gl_Position=u_matrix*vec4(floor(a_pos*.5)+g.xy/u_ratio,0,1);b=vec2(e*u_patternscale_a.x,f.y*u_patternscale_a.y+u_tex_y_a);c=vec2(e*u_patternscale_b.x,f.y*u_patternscale_b.y+u_tex_y_b);}","fragment":"precision mediump float;uniform vec2 u_linewidth;uniform vec4 u_color;uniform float u_blur,u_sdfgamma,u_mix;uniform sampler2D u_image;varying vec2 a,b,c;void main(){float d,e,f,g,h;d=length(a)*u_linewidth.s;e=clamp(min(d-(u_linewidth.t-u_blur),u_linewidth.s-d)/u_blur,0.,1.);f=texture2D(u_image,b).a;g=texture2D(u_image,c).a;h=mix(f,g,u_mix);e*=smoothstep(.5-u_sdfgamma,.5+u_sdfgamma,h);gl_FragColor=u_color*e;}"}, "outline": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_world;varying vec2 a;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(gl_Position.xy/gl_Position.w+1.)/2.*u_world;}","fragment":"precision mediump float;uniform vec4 u_color;varying vec2 a;void main(){float b,c;b=length(a-gl_FragCoord.xy);c=smoothstep(1.,0.,b);gl_FragColor=u_color*c;}"}, "pattern": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform mat3 u_patternmatrix_a,u_patternmatrix_b;attribute vec2 a_pos;varying vec2 a,b;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(u_patternmatrix_a*vec3(a_pos,1)).xy;b=(u_patternmatrix_b*vec3(a_pos,1)).xy;}","fragment":"precision mediump float;uniform float u_opacity,u_mix;uniform vec2 u_pattern_tl_a,u_pattern_br_a,u_pattern_tl_b,u_pattern_br_b;uniform sampler2D u_image;varying vec2 a,b;void main(){vec2 c,d,f,g;c=mod(a,1.);d=mix(u_pattern_tl_a,u_pattern_br_a,c);vec4 e,h;e=texture2D(u_image,d);f=mod(b,1.);g=mix(u_pattern_tl_b,u_pattern_br_b,f);h=texture2D(u_image,g);gl_FragColor=mix(e,h,u_mix)*u_opacity;}"}, "raster": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform vec2 u_tl_parent;uniform float u_scale_parent,u_buffer_scale;attribute vec2 a_pos,a_texture_pos;varying vec2 a,b;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(a_texture_pos/32767.-.5)/u_buffer_scale+.5;b=a*u_scale_parent+u_tl_parent;}","fragment":"precision mediump float;uniform float u_opacity0,u_opacity1,u_brightness_low,u_brightness_high,u_saturation_factor,u_contrast_factor;uniform sampler2D u_image0,u_image1;varying vec2 a,b;uniform vec3 u_spin_weights;void main(){vec4 c,d,e;c=texture2D(u_image0,a);d=texture2D(u_image1,b);e=c*u_opacity0+d*u_opacity1;vec3 f,h,i;f=e.rgb;f=vec3(dot(f,u_spin_weights.xyz),dot(f,u_spin_weights.zxy),dot(f,u_spin_weights.yzx));float g=(e.r+e.g+e.b)/3.;f+=(g-f)*u_saturation_factor;f=(f-.5)*u_contrast_factor+.5;h=vec3(u_brightness_low);i=vec3(u_brightness_high);gl_FragColor=vec4(mix(h,i,f),e.a);}"}, "icon": {"vertex":"precision mediump float;attribute vec2 a_pos,a_offset;attribute vec4 a_data1,a_data2;uniform mat4 u_matrix,u_exmatrix;uniform float u_zoom,u_fadedist,u_minfadezoom,u_maxfadezoom,u_fadezoom,u_opacity,u_extra;uniform bool u_skewed;uniform vec2 u_texsize;varying vec2 a;varying float b;void main(){vec2 c,e;c=a_data1.xy;float d,f,g,h,i,j;d=a_data1[2];e=a_data2.st;f=e[0];g=e[1];h=10.;i=2.-step(f,u_zoom)-(1.-step(g,u_zoom));j=clamp((u_fadezoom-d)/u_fadedist,0.,1.);if(u_fadedist>=0.)b=j;else b=1.-j;if(u_maxfadezoom<d)b=0.;if(u_minfadezoom>=d)b=1.;i+=step(b,0.);if(u_skewed){vec4 k=u_exmatrix*vec4(a_offset/64.,0,0);gl_Position=u_matrix*vec4(a_pos+k.xy,0,1);gl_Position.z+=i*gl_Position.w;}else{vec4 k=u_exmatrix*vec4(a_offset/64.,i,0);gl_Position=u_matrix*vec4(a_pos,0,1)+k;}a=c/u_texsize;b*=u_opacity;}","fragment":"precision mediump float;uniform sampler2D u_texture;varying vec2 a;varying float b;void main(){gl_FragColor=texture2D(u_texture,a)*b;}"}, "sdf": {"vertex":"precision mediump float;attribute vec2 a_pos,a_offset;attribute vec4 a_data1,a_data2;uniform mat4 u_matrix,u_exmatrix;uniform float u_zoom,u_fadedist,u_minfadezoom,u_maxfadezoom,u_fadezoom,u_extra;uniform bool u_skewed;uniform vec2 u_texsize;varying vec2 a;varying float b,c;void main(){vec2 d,f;d=a_data1.xy;float e,g,h,i,j,k,l;e=a_data1[2];f=a_data2.st;g=f[0];h=f[1];i=2.-step(g,u_zoom)-(1.-step(h,u_zoom));j=clamp((u_fadezoom-e)/u_fadedist,0.,1.);if(u_fadedist>=0.)b=j;else b=1.-j;if(u_maxfadezoom<e)b=0.;if(u_minfadezoom>=e)b=1.;i+=step(b,0.);if(u_skewed){vec4 k=u_exmatrix*vec4(a_offset/64.,0,0);gl_Position=u_matrix*vec4(a_pos+k.xy,0,1);gl_Position.z+=i*gl_Position.w;}else{vec4 k=u_exmatrix*vec4(a_offset/64.,i,0);gl_Position=u_matrix*vec4(a_pos,0,1)+k;}k=gl_Position.y/gl_Position.w;l=1./(1.-k*u_extra);c=l;a=d/u_texsize;}","fragment":"precision mediump float;uniform sampler2D u_texture;uniform vec4 u_color;uniform float u_buffer,u_gamma;varying vec2 a;varying float b,c;void main(){float d,e,f;d=u_gamma*c;e=texture2D(u_texture,a).a;f=smoothstep(u_buffer-d,u_buffer+d,e)*b;gl_FragColor=u_color*f;}"}, "collisionbox": {"vertex":"precision mediump float;attribute vec2 a_pos,a_extrude,a_data;uniform mat4 u_matrix;uniform float u_scale;varying float a,b;void main(){gl_Position=u_matrix*vec4(a_pos+a_extrude/u_scale,0,1);a=a_data.x;b=a_data.y;}","fragment":"precision mediump float;uniform float u_zoom,u_maxzoom;varying float a,b;void main(){float c=.5;gl_FragColor=vec4(0,1,0,1)*c;if(b>u_zoom)gl_FragColor=vec4(1,0,0,1)*c;if(u_zoom>=a)gl_FragColor=vec4(0,0,0,1)*c*.25;if(b>=u_maxzoom)gl_FragColor=vec4(0,0,1,1)*c*.2;}"} }; },{}],36:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var Evented = require('../util/evented'); var TilePyramid = require('./tile_pyramid'); var Source = require('./source'); var urlResolve = require('resolve-url'); module.exports = GeoJSONSource; /** * Create a GeoJSON data source instance given an options object * @class GeoJSONSource * @param {Object} [options] * @param {Object|String} options.data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files. * @param {Number} [options.maxzoom=14] Maximum zoom to preserve detail at. * @example * var sourceObj = new mapboxgl.GeoJSONSource({ * data: { * "type": "FeatureCollection", * "features": [{ * "type": "Feature", * "geometry": { * "type": "Point", * "coordinates": [ * -76.53063297271729, * 39.18174077994108 * ] * } * }] * } * }); * map.addSource('some id', sourceObj); // add * map.removeSource('some id'); // remove */ function GeoJSONSource(options) { options = options || {}; this._data = options.data; if (options.maxzoom !== undefined) this.maxzoom = options.maxzoom; this._pyramid = new TilePyramid({ tileSize: 512, minzoom: this.minzoom, maxzoom: this.maxzoom, cacheSize: 20, load: this._loadTile.bind(this), abort: this._abortTile.bind(this), unload: this._unloadTile.bind(this), add: this._addTile.bind(this), remove: this._removeTile.bind(this) }); } GeoJSONSource.prototype = util.inherit(Evented, /** @lends GeoJSONSource.prototype */{ minzoom: 0, maxzoom: 14, _dirty: true, /** * Update source geojson data and rerender map * * @param {Object|String} data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files. * @returns {GeoJSONSource} this */ setData: function(data) { this._data = data; this._dirty = true; this.fire('change'); if (this.map) this.update(this.map.transform); return this; }, onAdd: function(map) { this.map = map; }, loaded: function() { return this._loaded && this._pyramid.loaded(); }, update: function(transform) { if (this._dirty) { this._updateData(); } if (this._loaded) { this._pyramid.update(this.used, transform); } }, reload: function() { this._pyramid.reload(); }, render: Source._renderTiles, featuresAt: Source._vectorFeaturesAt, _updateData: function() { this._dirty = false; var data = this._data; if (typeof data === 'string') { data = urlResolve(window.location.href, data); } this.workerID = this.dispatcher.send('parse geojson', { data: data, tileSize: 512, source: this.id, maxZoom: this.maxzoom }, function(err) { if (err) { this.fire('error', {error: err}); return; } this._loaded = true; this._pyramid.reload(); this.fire('change'); }.bind(this)); }, _loadTile: function(tile) { var overscaling = tile.coord.z > this.maxzoom ? Math.pow(2, tile.coord.z - this.maxzoom) : 1; var params = { uid: tile.uid, coord: tile.coord, zoom: tile.coord.z, maxZoom: this.maxzoom, tileSize: 512, source: this.id, overscaling: overscaling, angle: this.map.transform.angle, pitch: this.map.transform.pitch, collisionDebug: this.map.collisionDebug }; tile.workerID = this.dispatcher.send('load geojson tile', params, function(err, data) { tile.unloadVectorData(this.map.painter); if (tile.aborted) return; if (err) { this.fire('tile.error', {tile: tile}); return; } tile.loadVectorData(data); this.fire('tile.load', {tile: tile}); }.bind(this), this.workerID); }, _abortTile: function(tile) { tile.aborted = true; }, _addTile: function(tile) { this.fire('tile.add', {tile: tile}); }, _removeTile: function(tile) { this.fire('tile.remove', {tile: tile}); }, _unloadTile: function(tile) { tile.unloadVectorData(this.map.painter); this.glyphAtlas.removeGlyphs(tile.uid); this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID); } }); },{"../util/evented":90,"../util/util":96,"./source":39,"./tile_pyramid":42,"resolve-url":115}],37:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); var VectorTileFeature = require('vector-tile').VectorTileFeature; module.exports = GeoJSONWrapper; // conform to vectortile api function GeoJSONWrapper(features) { this.features = features; this.length = features.length; } GeoJSONWrapper.prototype.feature = function(i) { return new FeatureWrapper(this.features[i]); }; function FeatureWrapper(feature) { this.type = feature.type; this.rawGeometry = feature.type === 1 ? [feature.geometry] : feature.geometry; this.properties = feature.tags; this.extent = 4096; } FeatureWrapper.prototype.loadGeometry = function() { var rings = this.rawGeometry; this.geometry = []; for (var i = 0; i < rings.length; i++) { var ring = rings[i], newRing = []; for (var j = 0; j < ring.length; j++) { newRing.push(new Point(ring[j][0], ring[j][1])); } this.geometry.push(newRing); } return this.geometry; }; FeatureWrapper.prototype.bbox = function() { if (!this.geometry) this.loadGeometry(); var rings = this.geometry, x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 0; j < ring.length; j++) { var coord = ring[j]; x1 = Math.min(x1, coord.x); x2 = Math.max(x2, coord.x); y1 = Math.min(y1, coord.y); y2 = Math.max(y2, coord.y); } } return [x1, y1, x2, y2]; }; FeatureWrapper.prototype.toGeoJSON = VectorTileFeature.prototype.toGeoJSON; },{"point-geometry":113,"vector-tile":117}],38:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var ajax = require('../util/ajax'); var Evented = require('../util/evented'); var Source = require('./source'); var normalizeURL = require('../util/mapbox').normalizeTileURL; module.exports = RasterTileSource; function RasterTileSource(options) { util.extend(this, util.pick(options, ['url', 'tileSize'])); Source._loadTileJSON.call(this, options); } RasterTileSource.prototype = util.inherit(Evented, { minzoom: 0, maxzoom: 22, tileSize: 512, _loaded: false, onAdd: function(map) { this.map = map; }, loaded: function() { return this._pyramid && this._pyramid.loaded(); }, update: function(transform) { if (this._pyramid) { this._pyramid.update(this.used, transform, this.map.style.rasterFadeDuration); } }, render: Source._renderTiles, _loadTile: function(tile) { ajax.getImage(normalizeURL(tile.coord.url(this.tiles), this.url), function(err, img) { if (tile.aborted) return; if (err) { this.fire('tile.error', {tile: tile}); return; } var gl = this.map.painter.gl; tile.texture = this.map.painter.getTexture(img.width); if (tile.texture) { gl.bindTexture(gl.TEXTURE_2D, tile.texture); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, img); } else { tile.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tile.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); tile.texture.size = img.width; } gl.generateMipmap(gl.TEXTURE_2D); tile.timeAdded = new Date().getTime(); this.map.animationLoop.set(this.style.rasterFadeDuration); tile.source = this; tile.loaded = true; this.fire('tile.load', {tile: tile}); }.bind(this)); }, _abortTile: function(tile) { tile.aborted = true; }, _addTile: function(tile) { this.fire('tile.add', {tile: tile}); }, _removeTile: function(tile) { this.fire('tile.remove', {tile: tile}); }, _unloadTile: function(tile) { if (tile.texture) this.map.painter.saveTexture(tile.texture); }, featuresAt: function(point, params, callback) { callback(null, []); } }); },{"../util/ajax":84,"../util/evented":90,"../util/mapbox":93,"../util/util":96,"./source":39}],39:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var ajax = require('../util/ajax'); var browser = require('../util/browser'); var TilePyramid = require('./tile_pyramid'); var TileCoord = require('./tile_coord'); var normalizeURL = require('../util/mapbox').normalizeSourceURL; exports._loadTileJSON = function(options) { var loaded = function(err, tileJSON) { if (err) { this.fire('error', {error: err}); return; } util.extend(this, util.pick(tileJSON, ['tiles', 'minzoom', 'maxzoom', 'attribution'])); this._pyramid = new TilePyramid({ tileSize: this.tileSize, cacheSize: 20, minzoom: this.minzoom, maxzoom: this.maxzoom, reparseOverscaled: this.reparseOverscaled, load: this._loadTile.bind(this), abort: this._abortTile.bind(this), unload: this._unloadTile.bind(this), add: this._addTile.bind(this), remove: this._removeTile.bind(this), redoPlacement: this._redoTilePlacement ? this._redoTilePlacement.bind(this) : undefined }); this.fire('load'); }.bind(this); if (options.url) { ajax.getJSON(normalizeURL(options.url), loaded); } else { browser.frame(loaded.bind(this, null, options)); } }; exports._renderTiles = function(layers, painter) { if (!this._pyramid) return; var ids = this._pyramid.renderedIDs(); for (var i = 0; i < ids.length; i++) { var tile = this._pyramid.getTile(ids[i]), // coord is different than tile.coord for wrapped tiles since the actual // tile object is shared between all the visible copies of that tile. coord = TileCoord.fromID(ids[i]), z = coord.z, x = coord.x, y = coord.y, w = coord.w; // if z > maxzoom then the tile is actually a overscaled maxzoom tile, // so calculate the matrix the maxzoom tile would use. z = Math.min(z, this.maxzoom); x += w * (1 << z); tile.calculateMatrices(z, x, y, painter.transform, painter); painter.drawTile(tile, layers); } }; exports._vectorFeaturesAt = function(coord, params, callback) { if (!this._pyramid) return callback(null, []); var result = this._pyramid.tileAt(coord); if (!result) return callback(null, []); this.dispatcher.send('query features', { uid: result.tile.uid, x: result.x, y: result.y, scale: result.scale, source: this.id, params: params }, callback, result.tile.workerID); }; /* * Create a tiled data source instance given an options object * * @param {Object} options * @param {String} options.type Either `raster` or `vector`. * @param {String} options.url A tile source URL. This should either be `mapbox://{mapid}` or a full `http[s]` url that points to a TileJSON endpoint. * @param {Array} options.tiles An array of tile sources. If `url` is not specified, `tiles` can be used instead to specify tile sources, as in the TileJSON spec. Other TileJSON keys such as `minzoom` and `maxzoom` can be specified in a source object if `tiles` is used. * @param {String} options.id An optional `id` to assign to the source * @param {Number} [options.tileSize=512] Optional tile size (width and height in pixels, assuming tiles are square). This option is only configurable for raster sources * @param {Number} options.cacheSize Optional max number of tiles to cache at any given time * @example * var sourceObj = new mapboxgl.Source.create({ * type: 'vector', * url: 'mapbox://mapbox.mapbox-streets-v5' * }); * map.addSource('some id', sourceObj); // add * map.removeSource('some id'); // remove */ exports.create = function(source) { // This is not at file scope in order to avoid a circular require. var sources = { vector: require('./vector_tile_source'), raster: require('./raster_tile_source'), geojson: require('./geojson_source'), video: require('./video_source') }; for (var type in sources) { if (source instanceof sources[type]) { return source; } } return new sources[source.type](source); }; },{"../util/ajax":84,"../util/browser":85,"../util/mapbox":93,"../util/util":96,"./geojson_source":36,"./raster_tile_source":38,"./tile_coord":41,"./tile_pyramid":42,"./vector_tile_source":43,"./video_source":44}],40:[function(require,module,exports){ 'use strict'; var glmatrix = require('gl-matrix'); var mat2 = glmatrix.mat2; var mat4 = glmatrix.mat4; var util = require('../util/util'); var BufferSet = require('../data/buffer/buffer_set'); module.exports = Tile; /** * A tile object is the combination of a Coordinate, which defines * its place, as well as a unique ID and data tracking for its content * * @param {Coordinate} coord * @param {number} size */ function Tile(coord, size) { this.coord = coord; this.uid = util.uniqueId(); this.loaded = false; this.uses = 0; this.tileSize = size; } Tile.prototype = { // todo unhardcode tileExtent: 4096, /** * Calculate the internal posMatrix that this tile uses to display * itself in a map, given a coordinate as (z, x, y) and a transform * @param {number} z * @param {number} x * @param {number} y * @param {Object} transform */ calculateMatrices: function(z, x, y, transform) { // Initialize model-view matrix that converts from the tile coordinates // to screen coordinates. var tileScale = Math.pow(2, z); var scale = transform.worldSize / tileScale; // TODO: remove this.scale = scale; // The position matrix this.posMatrix = new Float64Array(16); mat4.identity(this.posMatrix); mat4.translate(this.posMatrix, this.posMatrix, [x * scale, y * scale, 0]); mat4.scale(this.posMatrix, this.posMatrix, [ scale / this.tileExtent, scale / this.tileExtent, 1 ]); mat4.multiply(this.posMatrix, transform.getProjMatrix(), this.posMatrix); // The extrusion matrix. this.exMatrix = mat4.create(); mat4.ortho(this.exMatrix, 0, transform.width, transform.height, 0, 0, -1); //mat4.rotateZ(this.exMatrix, this.exMatrix, -transform.angle); // 2x2 matrix for rotating points this.rotationMatrix = mat2.create(); mat2.rotate(this.rotationMatrix, this.rotationMatrix, transform.angle); this.posMatrix = new Float32Array(this.posMatrix); }, /** * Given a coordinate position, zoom that coordinate to my zoom and * scale and return a position in x, y, scale * @param {Coordinate} coord * @returns {Object} position */ positionAt: function(coord, sourceMaxZoom) { coord = coord.zoomTo(Math.min(this.coord.z, sourceMaxZoom)); return { x: (coord.column - this.coord.x) * 4096, y: (coord.row - this.coord.y) * 4096, scale: this.scale }; }, /** * Given a data object with a 'buffers' property, load it into * this tile's elementGroups and buffers properties and set loaded * to true. If the data is null, like in the case of an empty * GeoJSON tile, no-op but still set loaded to true. * @param {Object} data * @returns {undefined} */ loadVectorData: function(data) { this.loaded = true; // empty GeoJSON tile if (!data) return; this.buffers = new BufferSet(data.buffers); this.elementGroups = data.elementGroups; this.tileExtent = data.extent; }, /** * given a data object and a GL painter, destroy and re-create * all of its buffers. * @param {Object} data * @param {Object} painter * @returns {undefined} */ reloadSymbolData: function(data, painter) { if (!this.buffers) { // the tile has been destroyed return; } this.buffers.glyphVertex.destroy(painter.gl); this.buffers.glyphElement.destroy(painter.gl); this.buffers.iconVertex.destroy(painter.gl); this.buffers.iconElement.destroy(painter.gl); this.buffers.collisionBoxVertex.destroy(painter.gl); var buffers = new BufferSet(data.buffers); this.buffers.glyphVertex = buffers.glyphVertex; this.buffers.glyphElement = buffers.glyphElement; this.buffers.iconVertex = buffers.iconVertex; this.buffers.iconElement = buffers.iconElement; this.buffers.collisionBoxVertex = buffers.collisionBoxVertex; for (var id in data.elementGroups) { this.elementGroups[id] = data.elementGroups[id]; } }, /** * Make sure that this tile doesn't own any data within a given * painter, so that it doesn't consume any memory or maintain * any references to the painter. * @param {Object} painter gl painter object * @returns {undefined} */ unloadVectorData: function(painter) { for (var b in this.buffers) { this.buffers[b].destroy(painter.gl); } this.buffers = null; } }; },{"../data/buffer/buffer_set":2,"../util/util":96,"gl-matrix":104}],41:[function(require,module,exports){ 'use strict'; module.exports = TileCoord; function TileCoord(z, x, y, w) { if (w === undefined) w = 0; this.z = z; this.x = x; this.y = y; this.w = w; // calculate id w *= 2; if (w < 0) w = w * -1 - 1; var dim = 1 << this.z; this.id = ((dim * dim * w + dim * this.y + this.x) * 32) + this.z; } TileCoord.prototype.toString = function() { return this.z + "/" + this.x + "/" + this.y; }; // Parse a packed integer id into a TileCoord object TileCoord.fromID = function(id) { var z = id % 32, dim = 1 << z; var xy = ((id - z) / 32); var x = xy % dim, y = ((xy - x) / dim) % dim; var w = Math.floor(xy / (dim * dim)); if (w % 2 !== 0) w = w * -1 - 1; w /= 2; return new TileCoord(z, x, y, w); }; // given a list of urls, choose a url template and return a tile URL TileCoord.prototype.url = function(urls, sourceMaxZoom) { return urls[(this.x + this.y) % urls.length] .replace('{prefix}', (this.x % 16).toString(16) + (this.y % 16).toString(16)) .replace('{z}', Math.min(this.z, sourceMaxZoom || this.z)) .replace('{x}', this.x) .replace('{y}', this.y); }; // Return the coordinate of the parent tile TileCoord.prototype.parent = function(sourceMaxZoom) { if (this.z === 0) return null; // the id represents an overscaled tile, return the same coordinates with a lower z if (this.z > sourceMaxZoom) { return new TileCoord(this.z - 1, this.x, this.y, this.w); } return new TileCoord(this.z - 1, Math.floor(this.x / 2), Math.floor(this.y / 2), this.w); }; TileCoord.prototype.wrapped = function() { return new TileCoord(this.z, this.x, this.y, 0); }; // Return the coordinates of the tile's children TileCoord.prototype.children = function(sourceMaxZoom) { if (this.z >= sourceMaxZoom) { // return a single tile coord representing a an overscaled tile return [new TileCoord(this.z + 1, this.x, this.y, this.w)]; } var z = this.z + 1; var x = this.x * 2; var y = this.y * 2; return [ new TileCoord(z, x, y, this.w), new TileCoord(z, x + 1, y, this.w), new TileCoord(z, x, y + 1, this.w), new TileCoord(z, x + 1, y + 1, this.w) ]; }; // Taken from polymaps src/Layer.js // https://github.com/simplegeo/polymaps/blob/master/src/Layer.js#L333-L383 function edge(a, b) { if (a.row > b.row) { var t = a; a = b; b = t; } return { x0: a.column, y0: a.row, x1: b.column, y1: b.row, dx: b.column - a.column, dy: b.row - a.row }; } function scanSpans(e0, e1, ymin, ymax, scanLine) { var y0 = Math.max(ymin, Math.floor(e1.y0)); var y1 = Math.min(ymax, Math.ceil(e1.y1)); // sort edges by x-coordinate if ((e0.x0 === e1.x0 && e0.y0 === e1.y0) ? (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) : (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) { var t = e0; e0 = e1; e1 = t; } // scan lines! var m0 = e0.dx / e0.dy; var m1 = e1.dx / e1.dy; var d0 = e0.dx > 0; // use y + 1 to compute x0 var d1 = e1.dx < 0; // use y + 1 to compute x1 for (var y = y0; y < y1; y++) { var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0; var x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0; scanLine(Math.floor(x1), Math.ceil(x0), y); } } function scanTriangle(a, b, c, ymin, ymax, scanLine) { var ab = edge(a, b), bc = edge(b, c), ca = edge(c, a); var t; // sort edges by y-length if (ab.dy > bc.dy) { t = ab; ab = bc; bc = t; } if (ab.dy > ca.dy) { t = ab; ab = ca; ca = t; } if (bc.dy > ca.dy) { t = bc; bc = ca; ca = t; } // scan span! scan span! if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine); if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine); } TileCoord.cover = function(z, bounds, actualZ) { var tiles = 1 << z; var t = {}; function scanLine(x0, x1, y) { var x, wx; if (y >= 0 && y <= tiles) { for (x = x0; x < x1; x++) { wx = (x + tiles) % tiles; var coord = new TileCoord(actualZ, wx, y, Math.floor(x / tiles)); t[coord.id] = coord; } } } // Divide the screen up in two triangles and scan each of them: // +---/ // | / | // /---+ scanTriangle(bounds[0], bounds[1], bounds[2], 0, tiles, scanLine); scanTriangle(bounds[2], bounds[3], bounds[0], 0, tiles, scanLine); return Object.keys(t).map(function(id) { return t[id]; }); }; },{}],42:[function(require,module,exports){ 'use strict'; var Tile = require('./tile'); var TileCoord = require('./tile_coord'); var Point = require('point-geometry'); var Cache = require('../util/mru_cache'); var util = require('../util/util'); module.exports = TilePyramid; /** * A tile pyramid is a specialized cache and datastructure * that contains tiles. It's used by sources to manage their * data. * * @param {Object} options * @param {number} options.tileSize * @param {number} options.minzoom * @param {number} options.maxzoom */ function TilePyramid(options) { this.tileSize = options.tileSize; this.minzoom = options.minzoom; this.maxzoom = options.maxzoom; this.reparseOverscaled = options.reparseOverscaled; this._load = options.load; this._abort = options.abort; this._unload = options.unload; this._add = options.add; this._remove = options.remove; this._redoPlacement = options.redoPlacement; this._tiles = {}; this._cache = new Cache(options.cacheSize, function(tile) { return this._unload(tile); }.bind(this)); } TilePyramid.prototype = { /** * Confirm that every tracked tile is loaded. * @returns {boolean} whether all tiles are loaded. * @private */ loaded: function() { for (var t in this._tiles) { if (!this._tiles[t].loaded) return false; } return true; }, /** * Return all tile ids ordered with z-order, and cast to numbers * @returns {Array<number>} ids * @private */ orderedIDs: function() { return Object.keys(this._tiles) .sort(function(a, b) { return (b % 32) - (a % 32); }) .map(function(id) { return +id; }); }, renderedIDs: function() { return this.orderedIDs().filter(function(id) { return this._tiles[id].loaded && !this._coveredTiles[id]; }.bind(this)); }, reload: function() { this._cache.reset(); for (var i in this._tiles) { this._load(this._tiles[i]); } }, /** * Get a specific tile by id * @param {string|number} id tile id * @returns {Object} tile * @private */ getTile: function(id) { return this._tiles[id]; }, /** * get the zoom level adjusted for the difference in map and source tilesizes * @param {Object} transform * @returns {number} zoom level * @private */ getZoom: function(transform) { return transform.zoom + Math.log(transform.tileSize / this.tileSize) / Math.LN2; }, /** * Return a zoom level that will cover all tiles in a given transform * @param {Object} transform * @returns {number} zoom level */ coveringZoomLevel: function(transform) { return Math.floor(this.getZoom(transform)); }, /** * Given a transform, return all coordinates that could cover that * transform for a covering zoom level. * @param {Object} transform * @returns {Array<Tile>} tiles */ coveringTiles: function(transform) { var z = this.coveringZoomLevel(transform); var actualZ = z; if (z < this.minzoom) return []; if (z > this.maxzoom) z = this.maxzoom; var tr = transform, tileCenter = tr.locationCoordinate(tr.center)._zoomTo(z), centerPoint = new Point(tileCenter.column - 0.5, tileCenter.row - 0.5); return TileCoord.cover(z, [ tr.pointCoordinate(new Point(0, 0))._zoomTo(z), tr.pointCoordinate(new Point(tr.width, 0))._zoomTo(z), tr.pointCoordinate(new Point(tr.width, tr.height))._zoomTo(z), tr.pointCoordinate(new Point(0, tr.height))._zoomTo(z) ], this.reparseOverscaled ? actualZ : z).sort(function(a, b) { return centerPoint.dist(a) - centerPoint.dist(b); }); }, /** * Recursively find children of the given tile (up to maxCoveringZoom) that are already loaded; * adds found tiles to retain object; returns true if children completely cover the tile * * @param {Coordinate} coord * @param {number} maxCoveringZoom * @param {boolean} retain * @returns {boolean} whether the operation was complete * @private */ findLoadedChildren: function(coord, maxCoveringZoom, retain) { var complete = true; var z = coord.z; var coords = coord.children(this.maxzoom); for (var i = 0; i < coords.length; i++) { var id = coords[i].id; if (this._tiles[id] && this._tiles[id].loaded) { retain[id] = true; } else { complete = false; if (z < maxCoveringZoom) { // Go further down the hierarchy to find more unloaded children. this.findLoadedChildren(coords[i], maxCoveringZoom, retain); } } } return complete; }, /** * Find a loaded parent of the given tile (up to minCoveringZoom); * adds the found tile to retain object and returns the tile if found * * @param {Coordinate} coord * @param {number} minCoveringZoom * @param {boolean} retain * @returns {Tile} tile object */ findLoadedParent: function(coord, minCoveringZoom, retain) { for (var z = coord.z - 1; z >= minCoveringZoom; z--) { coord = coord.parent(this.maxzoom); var tile = this._tiles[coord.id]; if (tile && tile.loaded) { retain[coord.id] = true; return tile; } } }, /** * Removes tiles that are outside the viewport and adds new tiles that * are inside the viewport. */ update: function(used, transform, fadeDuration) { var i; var coord; var tile; // Determine the overzooming/underzooming amounts. var zoom = Math.floor(this.getZoom(transform)); var minCoveringZoom = util.clamp(zoom - 10, this.minzoom, this.maxzoom); var maxCoveringZoom = util.clamp(zoom + 1, this.minzoom, this.maxzoom); // Retain is a list of tiles that we shouldn't delete, even if they are not // the most ideal tile for the current viewport. This may include tiles like // parent or child tiles that are *already* loaded. var retain = {}; var now = new Date().getTime(); // Covered is a list of retained tiles who's areas are full covered by other, // better, retained tiles. They are not drawn separately. this._coveredTiles = {}; var required = used ? this.coveringTiles(transform) : []; for (i = 0; i < required.length; i++) { coord = required[i]; tile = this.addTile(coord); retain[coord.id] = true; if (tile.loaded) continue; // The tile we require is not yet loaded. // Retain child or parent tiles that cover the same area. if (!this.findLoadedChildren(coord, maxCoveringZoom, retain)) { this.findLoadedParent(coord, minCoveringZoom, retain); } } for (var id in retain) { coord = TileCoord.fromID(id); tile = this._tiles[id]; if (tile && tile.timeAdded > now - (fadeDuration || 0)) { // This tile is still fading in. Find tiles to cross-fade with it. if (this.findLoadedChildren(coord, maxCoveringZoom, retain)) { this._coveredTiles[id] = true; retain[id] = true; } else { this.findLoadedParent(coord, minCoveringZoom, retain); } } } // Remove the tiles we don't need anymore. var remove = util.keysDifference(this._tiles, retain); for (i = 0; i < remove.length; i++) { this.removeTile(+remove[i]); } }, /** * Add a tile, given its coordinate, to the pyramid. * @param {Coordinate} coord * @returns {Coordinate} the coordinate. */ addTile: function(coord) { var tile = this._tiles[coord.id]; if (tile) return tile; var wrapped = coord.wrapped(); tile = this._tiles[wrapped.id]; if (!tile) { tile = this._cache.get(wrapped.id); if (tile && this._redoPlacement) { this._redoPlacement(tile); } } if (!tile) { var zoom = coord.z; var overscaling = zoom > this.maxzoom ? Math.pow(2, zoom - this.maxzoom) : 1; tile = new Tile(wrapped, this.tileSize * overscaling); this._load(tile); } tile.uses++; this._tiles[coord.id] = tile; this._add(tile, coord); return tile; }, /** * Remove a tile, given its id, from the pyramid * @param {string|number} id tile id * @returns {undefined} nothing * @private */ removeTile: function(id) { var tile = this._tiles[id]; if (!tile) return; tile.uses--; delete this._tiles[id]; this._remove(tile); if (tile.uses > 0) return; if (tile.loaded) { this._cache.add(tile.coord.wrapped().id, tile); } else { this._abort(tile); this._unload(tile); } }, /** * Remove all tiles from this pyramid */ clearTiles: function() { for (var id in this._tiles) this.removeTile(id); this._cache.reset(); }, /** * For a given coordinate, search through our current tiles and attempt * to find a tile at that point * @param {Coordinate} coord * @returns {Object} tile * @private */ tileAt: function(coord) { var ids = this.orderedIDs(); for (var i = 0; i < ids.length; i++) { var tile = this._tiles[ids[i]]; var pos = tile.positionAt(coord, this.maxzoom); if (pos && pos.x >= 0 && pos.x < 4096 && pos.y >= 0 && pos.y < 4096) { // The click is within the viewport. There is only ever one tile in // a layer that has this property. return { tile: tile, x: pos.x, y: pos.y, scale: pos.scale }; } } } }; },{"../util/mru_cache":94,"../util/util":96,"./tile":40,"./tile_coord":41,"point-geometry":113}],43:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var Evented = require('../util/evented'); var Source = require('./source'); module.exports = VectorTileSource; function VectorTileSource(options) { util.extend(this, util.pick(options, ['url', 'tileSize'])); if (this.tileSize !== 512) { throw new Error('vector tile sources must have a tileSize of 512'); } Source._loadTileJSON.call(this, options); } VectorTileSource.prototype = util.inherit(Evented, { minzoom: 0, maxzoom: 22, tileSize: 512, reparseOverscaled: true, _loaded: false, onAdd: function(map) { this.map = map; }, loaded: function() { return this._pyramid && this._pyramid.loaded(); }, update: function(transform) { if (this._pyramid) { this._pyramid.update(this.used, transform); } }, reload: function() { this._pyramid.reload(); }, redoPlacement: function() { if (!this._pyramid) { return; } var ids = this._pyramid.orderedIDs(); for (var i = 0; i < ids.length; i++) { var tile = this._pyramid.getTile(ids[i]); this._redoTilePlacement(tile); } }, render: Source._renderTiles, featuresAt: Source._vectorFeaturesAt, _loadTile: function(tile) { var overscaling = tile.coord.z > this.maxzoom ? Math.pow(2, tile.coord.z - this.maxzoom) : 1; var params = { url: tile.coord.url(this.tiles, this.maxzoom), uid: tile.uid, coord: tile.coord, zoom: tile.coord.z, maxZoom: this.maxzoom, tileSize: this.tileSize * overscaling, source: this.id, overscaling: overscaling, angle: this.map.transform.angle, pitch: this.map.transform.pitch, collisionDebug: this.map.collisionDebug }; if (tile.workerID) { this.dispatcher.send('reload tile', params, this._tileLoaded.bind(this, tile), tile.workerID); } else { tile.workerID = this.dispatcher.send('load tile', params, this._tileLoaded.bind(this, tile)); } }, _tileLoaded: function(tile, err, data) { if (tile.aborted) return; if (err) { this.fire('tile.error', {tile: tile}); return; } tile.loadVectorData(data); if (tile.redoWhenDone) { tile.redoWhenDone = false; this._redoTilePlacement(tile); } this.fire('tile.load', {tile: tile}); }, _abortTile: function(tile) { tile.aborted = true; this.dispatcher.send('abort tile', { uid: tile.uid, source: this.id }, null, tile.workerID); }, _addTile: function(tile) { this.fire('tile.add', {tile: tile}); }, _removeTile: function(tile) { this.fire('tile.remove', {tile: tile}); }, _unloadTile: function(tile) { tile.unloadVectorData(this.map.painter); this.glyphAtlas.removeGlyphs(tile.uid); this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID); }, _redoTilePlacement: function(tile) { if (!tile.loaded || tile.redoingPlacement) { tile.redoWhenDone = true; return; } tile.redoingPlacement = true; this.dispatcher.send('redo placement', { uid: tile.uid, source: this.id, angle: this.map.transform.angle, pitch: this.map.transform.pitch, collisionDebug: this.map.collisionDebug }, done.bind(this), tile.workerID); function done(_, data) { tile.reloadSymbolData(data, this.map.painter); this.fire('tile.load', {tile: tile}); tile.redoingPlacement = false; if (tile.redoWhenDone) { this._redoTilePlacement(tile); tile.redoWhenDone = false; } } } }); },{"../util/evented":90,"../util/util":96,"./source":39}],44:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var Tile = require('./tile'); var LatLng = require('../geo/lat_lng'); var Point = require('point-geometry'); var Evented = require('../util/evented'); var Coordinate = require('../geo/coordinate'); var ajax = require('../util/ajax'); module.exports = VideoSource; /** * Create a Video data source instance given an options object * @class VideoSource * @param {Object} [options] * @param {String|Array} options.url A string or array of URL(s) to video files * @param {Array} options.coordinates lat,lng coordinates in order clockwise starting at the top left: tl, tr, br, bl * @example * var sourceObj = new mapboxgl.VideoSource({ * url: [ * 'https://www.mapbox.com/videos/baltimore-smoke.mp4', * 'https://www.mapbox.com/videos/baltimore-smoke.webm' * ], * coordinates: [ * [39.18579907229748, -76.54335737228394], * [39.1838364847587, -76.52803659439087], * [39.17683392507606, -76.5295386314392], * [39.17876344106642, -76.54520273208618] * ] * }); * map.addSource('some id', sourceObj); // add * map.removeSource('some id'); // remove */ function VideoSource(options) { this.coordinates = options.coordinates; ajax.getVideo(options.url, function(err, video) { // @TODO handle errors via event. if (err) return; this.video = video; this.video.loop = true; var loopID; // start repainting when video starts playing this.video.addEventListener('playing', function() { loopID = this.map.style.animationLoop.set(Infinity); this.map._rerender(); }.bind(this)); // stop repainting when video stops this.video.addEventListener('pause', function() { this.map.style.animationLoop.cancel(loopID); }.bind(this)); this._loaded = true; if (this.map) { this.video.play(); this.createTile(); this.fire('change'); } }.bind(this)); } VideoSource.prototype = util.inherit(Evented, { /** * Return the HTML video element. * * @returns {Object} */ getVideo: function() { return this.video; }, onAdd: function(map) { this.map = map; if (this.video) { this.video.play(); this.createTile(); } }, createTile: function() { /* * Calculate which mercator tile is suitable for rendering the video in * and create a buffer with the corner coordinates. These coordinates * may be outside the tile, because raster tiles aren't clipped when rendering. */ var map = this.map; var coords = this.coordinates.map(function(latlng) { var loc = LatLng.convert(latlng); return map.transform.locationCoordinate(loc).zoomTo(0); }); var minX = Infinity; var minY = Infinity; var maxX = -Infinity; var maxY = -Infinity; for (var i = 0; i < coords.length; i++) { minX = Math.min(minX, coords[i].column); minY = Math.min(minY, coords[i].row); maxX = Math.max(maxX, coords[i].column); maxY = Math.max(maxY, coords[i].row); } var dx = maxX - minX; var dy = maxY - minY; var dMax = Math.max(dx, dy); var center = new Coordinate((minX + maxX) / 2, (minY + maxY) / 2, 0) .zoomTo(Math.floor(-Math.log(dMax) / Math.LN2)); var tileExtent = 4096; var tileCoords = coords.map(function(coord) { var zoomedCoord = coord.zoomTo(center.zoom); return new Point( Math.round((zoomedCoord.column - center.column) * tileExtent), Math.round((zoomedCoord.row - center.row) * tileExtent)); }); var gl = map.painter.gl; var maxInt16 = 32767; var array = new Int16Array([ tileCoords[0].x, tileCoords[0].y, 0, 0, tileCoords[1].x, tileCoords[1].y, maxInt16, 0, tileCoords[3].x, tileCoords[3].y, 0, maxInt16, tileCoords[2].x, tileCoords[2].y, maxInt16, maxInt16 ]); this.tile = new Tile(); this.tile.buckets = {}; this.tile.boundsBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.tile.boundsBuffer); gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); this.center = center; }, loaded: function() { return this.video && this.video.readyState >= 2; }, update: function() { // noop }, render: function(layers, painter) { if (!this._loaded) return; if (this.video.readyState < 2) return; // not enough data for current position var c = this.center; this.tile.calculateMatrices(c.zoom, c.column, c.row, this.map.transform, painter); var gl = painter.gl; if (!this.tile.texture) { this.tile.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video); } else { gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video); } painter.drawLayers(layers, this.tile.posMatrix, this.tile); }, featuresAt: function(point, params, callback) { return callback(null, []); } }); },{"../geo/coordinate":17,"../geo/lat_lng":18,"../util/ajax":84,"../util/evented":90,"../util/util":96,"./tile":40,"point-geometry":113}],45:[function(require,module,exports){ 'use strict'; var Actor = require('../util/actor'); var WorkerTile = require('./worker_tile'); var util = require('../util/util'); var ajax = require('../util/ajax'); var vt = require('vector-tile'); var Protobuf = require('pbf'); var geojsonvt = require('geojson-vt'); var GeoJSONWrapper = require('./geojson_wrapper'); module.exports = function(self) { return new Worker(self); }; function Worker(self) { this.self = self; this.actor = new Actor(self, this); this.loading = {}; this.loaded = {}; this.layers = []; this.geoJSONIndexes = {}; } util.extend(Worker.prototype, { 'set layers': function(layers) { this.layers = layers; }, 'load tile': function(params, callback) { var source = params.source, uid = params.uid; if (!this.loading[source]) this.loading[source] = {}; var tile = this.loading[source][uid] = new WorkerTile(params); tile.xhr = ajax.getArrayBuffer(params.url, done.bind(this)); function done(err, data) { delete this.loading[source][uid]; if (err) return callback(err); tile.data = new vt.VectorTile(new Protobuf(new Uint8Array(data))); tile.parse(tile.data, this.layers, this.actor, callback); this.loaded[source] = this.loaded[source] || {}; this.loaded[source][uid] = tile; } }, 'reload tile': function(params, callback) { var loaded = this.loaded[params.source], uid = params.uid; if (loaded && loaded[uid]) { var tile = loaded[uid]; tile.parse(tile.data, this.layers, this.actor, callback); } }, 'abort tile': function(params) { var loading = this.loading[params.source], uid = params.uid; if (loading && loading[uid]) { loading[uid].xhr.abort(); delete loading[uid]; } }, 'remove tile': function(params) { var loaded = this.loaded[params.source], uid = params.uid; if (loaded && loaded[uid]) { delete loaded[uid]; } }, 'redo placement': function(params, callback) { var loaded = this.loaded[params.source], loading = this.loading[params.source], uid = params.uid; if (loaded && loaded[uid]) { var tile = loaded[uid]; var result = tile.redoPlacement(params.angle, params.pitch, params.collisionDebug); if (result.result) { callback(null, result.result, result.transferables); } } else if (loading && loading[uid]) { loading[uid].angle = params.angle; } }, 'parse geojson': function(params, callback) { var indexData = function(err, data) { if (err) return callback(err); this.geoJSONIndexes[params.source] = geojsonvt(data, {baseZoom: params.maxZoom}); callback(null); }.bind(this); // TODO accept params.url for urls instead // Not, because of same origin issues, urls must either include an // explicit origin or absolute path. // ie: /foo/bar.json or http://example.com/bar.json // but not ../foo/bar.json if (typeof params.data === 'string') { ajax.getJSON(params.data, indexData); } else indexData(null, params.data); }, 'load geojson tile': function(params, callback) { var source = params.source, coord = params.coord; // console.time('tile ' + coord.z + ' ' + coord.x + ' ' + coord.y); var geoJSONTile = this.geoJSONIndexes[source].getTile(coord.z, coord.x, coord.y); // console.timeEnd('tile ' + coord.z + ' ' + coord.x + ' ' + coord.y); // if (!geoJSONTile) console.log('not found', this.geoJSONIndexes[source], coord); if (!geoJSONTile) return callback(null, null); // nothing in the given tile var tile = new WorkerTile(params); tile.parse(new GeoJSONWrapper(geoJSONTile.features), this.layers, this.actor, callback); this.loaded[source] = this.loaded[source] || {}; this.loaded[source][params.uid] = tile; }, 'query features': function(params, callback) { var tile = this.loaded[params.source] && this.loaded[params.source][params.uid]; if (tile) { tile.featureTree.query(params, callback); } else { callback(null, []); } } }); },{"../util/actor":83,"../util/ajax":84,"../util/util":96,"./geojson_wrapper":37,"./worker_tile":46,"geojson-vt":101,"pbf":111,"vector-tile":117}],46:[function(require,module,exports){ 'use strict'; var FeatureTree = require('../data/feature_tree'); var Collision = require('../symbol/collision_tile'); var BufferSet = require('../data/buffer/buffer_set'); var createBucket = require('../data/create_bucket'); module.exports = WorkerTile; function WorkerTile(params) { this.coord = params.coord; this.uid = params.uid; this.zoom = params.zoom; this.maxZoom = params.maxZoom; this.tileSize = params.tileSize; this.source = params.source; this.overscaling = params.overscaling; this.angle = params.angle; this.pitch = params.pitch; this.collisionDebug = params.collisionDebug; this.stacks = {}; } WorkerTile.prototype.parse = function(data, layers, actor, callback) { this.status = 'parsing'; this.featureTree = new FeatureTree(this.coord, this.overscaling); var i, k, tile = this, layer, bucket, buffers = new BufferSet(), collision = this.collision = new Collision(this.zoom, 4096, this.tileSize), buckets = {}, bucketsInOrder = this.bucketsInOrder = [], bucketsBySourceLayer = {}; collision.reset(this.angle, this.pitch); // Map non-ref layers to buckets. for (i = 0; i < layers.length; i++) { layer = layers[i]; if (layer.source !== this.source) continue; if (layer.ref) continue; var minzoom = layer.minzoom; if (minzoom && this.zoom < minzoom && minzoom < this.maxZoom) continue; var maxzoom = layer.maxzoom; if (maxzoom && this.zoom >= maxzoom) continue; var visibility = layer.layout.visibility; if (visibility === 'none') continue; bucket = createBucket(layer, buffers, collision, this.zoom, this.overscaling, this.collisionDebug); bucket.layers = [layer.id]; buckets[bucket.id] = bucket; bucketsInOrder.push(bucket); if (data.layers) { // vectortile var sourceLayer = layer['source-layer']; if (!bucketsBySourceLayer[sourceLayer]) bucketsBySourceLayer[sourceLayer] = {}; bucketsBySourceLayer[sourceLayer][bucket.id] = bucket; } else { // geojson tile bucketsBySourceLayer[bucket.id] = bucket; } } // Index ref layers. for (i = 0; i < layers.length; i++) { layer = layers[i]; if (layer.source !== this.source) continue; if (!layer.ref) continue; bucket = buckets[layer.ref]; if (!bucket) continue; bucket.layers.push(layer.id); } var extent = 4096; // read each layer, and sort its features into buckets if (data.layers) { // vectortile for (k in bucketsBySourceLayer) { layer = data.layers[k]; if (!layer) continue; if (layer.extent) extent = layer.extent; sortLayerIntoBuckets(layer, bucketsBySourceLayer[k]); } } else { // geojson sortLayerIntoBuckets(data, bucketsBySourceLayer); } function sortLayerIntoBuckets(layer, buckets) { for (var i = 0; i < layer.length; i++) { var feature = layer.feature(i); for (var key in buckets) { var bucket = buckets[key]; if (bucket.filter(feature)) { bucket.features.push(feature); } } } } var prevPlacementBucket; var remaining = bucketsInOrder.length; /* * The async parsing here is a bit tricky. * Some buckets depend on resources that may need to be loaded async (glyphs). * Some buckets need to be parsed in order (to get collision priorities right). * * Dependencies calls are initiated first to get those rolling. * Buckets that don't need to be parsed in order, aren't to save time. */ for (i = 0; i < bucketsInOrder.length; i++) { bucket = bucketsInOrder[i]; // Link buckets that need to be parsed in order if (bucket.collision) { if (prevPlacementBucket) { prevPlacementBucket.next = bucket; } else { bucket.previousPlaced = true; } prevPlacementBucket = bucket; } if (bucket.getDependencies) { bucket.getDependencies(this, actor, dependenciesDone(bucket)); } // immediately parse buckets where order doesn't matter and no dependencies if (!bucket.collision && !bucket.getDependencies) { parseBucket(tile, bucket); } } function dependenciesDone(bucket) { return function(err) { bucket.dependenciesLoaded = true; parseBucket(tile, bucket, err); }; } function parseBucket(tile, bucket, skip) { if (bucket.getDependencies && !bucket.dependenciesLoaded) return; if (bucket.collision && !bucket.previousPlaced) return; if (!skip) { var now = Date.now(); if (bucket.features.length) bucket.addFeatures(); var time = Date.now() - now; if (bucket.interactive) { for (var i = 0; i < bucket.features.length; i++) { var feature = bucket.features[i]; tile.featureTree.insert(feature.bbox(), bucket.layers, feature); } } if (typeof self !== 'undefined') { self.bucketStats = self.bucketStats || {_total: 0}; self.bucketStats._total += time; self.bucketStats[bucket.id] = (self.bucketStats[bucket.id] || 0) + time; } } remaining--; if (!remaining) { done(); return; } // try parsing the next bucket, if it is ready if (bucket.next) { bucket.next.previousPlaced = true; parseBucket(tile, bucket.next); } } function done() { tile.status = 'done'; if (tile.redoPlacementAfterDone) { var result = tile.redoPlacement(tile.angle, tile.pitch).result; buffers.glyphVertex = result.buffers.glyphVertex; buffers.iconVertex = result.buffers.iconVertex; buffers.collisionBoxVertex = result.buffers.collisionBoxVertex; } var transferables = [], elementGroups = {}; for (k in buffers) { transferables.push(buffers[k].array); } for (k in buckets) { elementGroups[k] = buckets[k].elementGroups; } callback(null, { elementGroups: elementGroups, buffers: buffers, extent: extent }, transferables); } }; WorkerTile.prototype.redoPlacement = function(angle, pitch, collisionDebug) { if (this.status !== 'done') { this.redoPlacementAfterDone = true; this.angle = angle; return {}; } var buffers = new BufferSet(); var transferables = []; var elementGroups = {}; var collision = this.collision; collision.reset(angle, pitch); var bucketsInOrder = this.bucketsInOrder; for (var i = 0; i < bucketsInOrder.length; i++) { var bucket = bucketsInOrder[i]; if (bucket.type === 'symbol') { bucket.placeFeatures(buffers, collisionDebug); elementGroups[bucket.id] = bucket.elementGroups; } } for (var k in buffers) { transferables.push(buffers[k].array); } return { result: { elementGroups: elementGroups, buffers: buffers }, transferables: transferables }; }; },{"../data/buffer/buffer_set":2,"../data/create_bucket":11,"../data/feature_tree":13,"../symbol/collision_tile":64}],47:[function(require,module,exports){ 'use strict'; module.exports = AnimationLoop; function AnimationLoop() { this.n = 0; this.times = []; } // Are all animations done? AnimationLoop.prototype.stopped = function() { this.times = this.times.filter(function(t) { return t.time >= (new Date()).getTime(); }); return !this.times.length; }; // Add a new animation that will run t milliseconds // Returns an id that can be used to cancel it layer AnimationLoop.prototype.set = function(t) { this.times.push({ id: this.n, time: t + (new Date()).getTime() }); return this.n++; }; // Cancel an animation AnimationLoop.prototype.cancel = function(n) { this.times = this.times.filter(function(t) { return t.id !== n; }); }; },{}],48:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented'); var ajax = require('../util/ajax'); var browser = require('../util/browser'); module.exports = ImageSprite; function ImageSprite(base) { this.base = base; this.retina = browser.devicePixelRatio > 1; base = this.base + (this.retina ? '@2x' : ''); ajax.getJSON(base + '.json', function(err, data) { if (err) { this.fire('error', {error: err}); return; } this.data = data; if (this.img) this.fire('load'); }.bind(this)); ajax.getImage(base + '.png', function(err, img) { if (err) { this.fire('error', {error: err}); return; } // premultiply the sprite var data = img.getData(); var newdata = img.data = new Uint8Array(data.length); for (var i = 0; i < data.length; i += 4) { var alpha = data[i + 3] / 255; newdata[i + 0] = data[i + 0] * alpha; newdata[i + 1] = data[i + 1] * alpha; newdata[i + 2] = data[i + 2] * alpha; newdata[i + 3] = data[i + 3]; } this.img = img; if (this.data) this.fire('load'); }.bind(this)); } ImageSprite.prototype = Object.create(Evented); ImageSprite.prototype.toJSON = function() { return this.base; }; ImageSprite.prototype.loaded = function() { return !!(this.data && this.img); }; ImageSprite.prototype.resize = function(/*gl*/) { if (browser.devicePixelRatio > 1 !== this.retina) { var newSprite = new ImageSprite(this.base); newSprite.on('load', function() { this.img = newSprite.img; this.data = newSprite.data; this.retina = newSprite.retina; }.bind(this)); } }; function SpritePosition() {} SpritePosition.prototype = { x: 0, y: 0, width: 0, height: 0, pixelRatio: 1, sdf: false }; ImageSprite.prototype.getSpritePosition = function(name) { if (!this.loaded()) return new SpritePosition(); var pos = this.data && this.data[name]; if (pos && this.img) return pos; return new SpritePosition(); }; },{"../util/ajax":84,"../util/browser":85,"../util/evented":90}],49:[function(require,module,exports){ 'use strict'; var reference = require('./reference'); module.exports = {}; reference.layout.forEach(function(className) { var Properties = function(props) { for (var p in props) { this[p] = props[p]; } }; var properties = reference[className]; for (var prop in properties) { if (properties[prop].default === undefined) continue; Properties.prototype[prop] = properties[prop].default; } module.exports[className.replace('layout_', '')] = Properties; }); },{"./reference":51}],50:[function(require,module,exports){ 'use strict'; var reference = require('./reference'); var parseCSSColor = require('csscolorparser').parseCSSColor; module.exports = {}; reference.paint.forEach(function(className) { var Calculated = function() {}; var properties = reference[className]; for (var p in properties) { var prop = properties[p], value = prop.default; if (value === undefined) continue; if (prop.type === 'color') value = parseCSSColor(value); Calculated.prototype[p] = value; } Calculated.prototype.hidden = false; module.exports[className.replace('paint_', '')] = Calculated; }); },{"./reference":51,"csscolorparser":97}],51:[function(require,module,exports){ module.exports = require('mapbox-gl-style-spec/reference/latest'); },{"mapbox-gl-style-spec/reference/latest":108}],52:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented'); var Source = require('../source/source'); var StyleLayer = require('./style_layer'); var ImageSprite = require('./image_sprite'); var GlyphSource = require('../symbol/glyph_source'); var GlyphAtlas = require('../symbol/glyph_atlas'); var SpriteAtlas = require('../symbol/sprite_atlas'); var LineAtlas = require('../render/line_atlas'); var util = require('../util/util'); var ajax = require('../util/ajax'); var normalizeURL = require('../util/mapbox').normalizeStyleURL; var browser = require('../util/browser'); var Dispatcher = require('../util/dispatcher'); var AnimationLoop = require('./animation_loop'); var validate = require('mapbox-gl-style-spec/lib/validate/latest'); module.exports = Style; function Style(stylesheet, animationLoop) { this.animationLoop = animationLoop || new AnimationLoop(); this.dispatcher = new Dispatcher(Math.max(browser.hardwareConcurrency - 1, 1), this); this.glyphAtlas = new GlyphAtlas(1024, 1024); this.spriteAtlas = new SpriteAtlas(512, 512); this.spriteAtlas.resize(browser.devicePixelRatio); this.lineAtlas = new LineAtlas(256, 512); this._layers = {}; this._order = []; this._groups = []; this.sources = {}; this.zoomHistory = {}; util.bindAll([ '_forwardSourceEvent', '_forwardTileEvent', '_redoPlacement' ], this); var loaded = function(err, stylesheet) { if (err) { this.fire('error', {error: err}); return; } var valid = validate(stylesheet); if (valid.length) { valid.forEach(function(e) { throw new Error(e.message); }); } this._loaded = true; this.stylesheet = stylesheet; var sources = stylesheet.sources; for (var id in sources) { this.addSource(id, sources[id]); } if (stylesheet.sprite) { this.sprite = new ImageSprite(stylesheet.sprite); this.sprite.on('load', this.fire.bind(this, 'change')); } this.glyphSource = new GlyphSource(stylesheet.glyphs, this.glyphAtlas); this._resolve(); this.fire('load'); }.bind(this); if (typeof stylesheet === 'string') { ajax.getJSON(normalizeURL(stylesheet), loaded); } else { browser.frame(loaded.bind(this, null, stylesheet)); } } Style.prototype = util.inherit(Evented, { _loaded: false, loaded: function() { if (!this._loaded) return false; for (var id in this.sources) if (!this.sources[id].loaded()) return false; if (this.sprite && !this.sprite.loaded()) return false; return true; }, _resolve: function() { var id, layer; this._layers = {}; this._order = []; for (var i = 0; i < this.stylesheet.layers.length; i++) { layer = new StyleLayer(this.stylesheet.layers[i], this.stylesheet.constants || {}); this._layers[layer.id] = layer; this._order.push(layer.id); } // Resolve layout properties. for (id in this._layers) { this._layers[id].resolveLayout(); } // Resolve reference and paint properties. for (id in this._layers) { this._layers[id].resolveReference(this._layers); this._layers[id].resolvePaint(); } this._groupLayers(); this._broadcastLayers(); }, _groupLayers: function() { var group; this._groups = []; // Split into groups of consecutive top-level layers with the same source. for (var i = 0; i < this._order.length; ++i) { var layer = this._layers[this._order[i]]; if (!group || layer.source !== group.source) { group = []; group.source = layer.source; this._groups.push(group); } group.push(layer); } }, _broadcastLayers: function() { var ordered = []; for (var id in this._layers) { ordered.push(this._layers[id].json()); } this.dispatcher.broadcast('set layers', ordered); }, _cascade: function(classes, options) { if (!this._loaded) return; options = options || { transition: true }; for (var id in this._layers) { this._layers[id].cascade(classes, options, this.stylesheet.transition || {}, this.animationLoop); } this.fire('change'); }, _recalculate: function(z) { for (var id in this.sources) this.sources[id].used = false; this._updateZoomHistory(z); this.rasterFadeDuration = 300; for (id in this._layers) { var layer = this._layers[id]; if (layer.recalculate(z, this.zoomHistory) && layer.source) { this.sources[layer.source].used = true; } } var maxZoomTransitionDuration = 300; if (Math.floor(this.z) !== Math.floor(z)) { this.animationLoop.set(maxZoomTransitionDuration); } this.z = z; this.fire('zoom'); }, _updateZoomHistory: function(z) { var zh = this.zoomHistory; if (zh.lastIntegerZoom === undefined) { // first time zh.lastIntegerZoom = Math.floor(z); zh.lastIntegerZoomTime = 0; zh.lastZoom = z; } // check whether an integer zoom level as passed since the last frame // and if yes, record it with the time. Used for transitioning patterns. if (Math.floor(zh.lastZoom) < Math.floor(z)) { zh.lastIntegerZoom = Math.floor(z); zh.lastIntegerZoomTime = Date.now(); } else if (Math.floor(zh.lastZoom) > Math.floor(z)) { zh.lastIntegerZoom = Math.floor(z + 1); zh.lastIntegerZoomTime = Date.now(); } zh.lastZoom = z; }, addSource: function(id, source) { if (this.sources[id] !== undefined) { throw new Error('There is already a source with this ID'); } source = Source.create(source); this.sources[id] = source; source.id = id; source.style = this; source.dispatcher = this.dispatcher; source.glyphAtlas = this.glyphAtlas; source .on('load', this._forwardSourceEvent) .on('error', this._forwardSourceEvent) .on('change', this._forwardSourceEvent) .on('tile.add', this._forwardTileEvent) .on('tile.load', this._forwardTileEvent) .on('tile.error', this._forwardTileEvent) .on('tile.remove', this._forwardTileEvent); this.fire('source.add', {source: source}); return this; }, /** * Remove a source from this stylesheet, given its id. * @param {String} id id of the source to remove * @returns {Style} this style * @throws {Error} if no source is found with the given ID * @private */ removeSource: function(id) { if (this.sources[id] === undefined) { throw new Error('There is no source with this ID'); } var source = this.sources[id]; delete this.sources[id]; source .off('load', this._forwardSourceEvent) .off('error', this._forwardSourceEvent) .off('change', this._forwardSourceEvent) .off('tile.add', this._forwardTileEvent) .off('tile.load', this._forwardTileEvent) .off('tile.error', this._forwardTileEvent) .off('tile.remove', this._forwardTileEvent); this.fire('source.remove', {source: source}); return this; }, /** * Get a source by id. * @param {String} id id of the desired source * @returns {Object} source * @private */ getSource: function(id) { return this.sources[id]; }, /** * Add a layer to the map style. The layer will be inserted before the layer with * ID `before`, or appended if `before` is omitted. * @param {StyleLayer|Object} layer * @param {string=} before ID of an existing layer to insert before * @fires layer.add * @returns {Style} `this` */ addLayer: function(layer, before) { if (this._layers[layer.id] !== undefined) { throw new Error('There is already a layer with this ID'); } if (!(layer instanceof StyleLayer)) { layer = new StyleLayer(layer, this.stylesheet.constants || {}); } this._layers[layer.id] = layer; this._order.splice(before ? this._order.indexOf(before) : Infinity, 0, layer.id); layer.resolveLayout(); layer.resolveReference(this._layers); layer.resolvePaint(); this._groupLayers(); this._broadcastLayers(); this.fire('layer.add', {layer: layer}); return this; }, /** * Remove a layer from this stylesheet, given its id. * @param {String} id id of the layer to remove * @returns {Style} this style * @throws {Error} if no layer is found with the given ID * @private */ removeLayer: function(id) { var layer = this._layers[id]; if (layer === undefined) { throw new Error('There is no layer with this ID'); } for (var i in this._layers) { if (this._layers[i].ref === id) { this.removeLayer(i); } } delete this._layers[id]; this._order.splice(this._order.indexOf(id), 1); this._groupLayers(); this._broadcastLayers(); this.fire('layer.remove', {layer: layer}); return this; }, /** * Get a layer by id. * @param {String} id id of the desired layer * @returns {Layer} layer * @private */ getLayer: function(id) { return this._layers[id]; }, /** * If a layer has a `ref` property that makes it derive some values * from another layer, return that referent layer. Otherwise, * returns the layer itself. * @param {String} id the layer's id * @returns {Layer} the referent layer or the layer itself * @private */ getReferentLayer: function(id) { var layer = this.getLayer(id); if (layer.ref) { layer = this.getLayer(layer.ref); } return layer; }, setFilter: function(layer, filter) { layer = this.getReferentLayer(layer); layer.filter = filter; this._broadcastLayers(); this.sources[layer.source].reload(); }, /** * Get a layer's filter object * @param {String} layer the layer to inspect * @returns {*} the layer's filter, if any * @private */ getFilter: function(layer) { return this.getReferentLayer(layer).filter; }, setLayoutProperty: function(layer, name, value) { layer = this.getReferentLayer(layer); layer.setLayoutProperty(name, value); this._broadcastLayers(); this.sources[layer.source].reload(); }, /** * Get a layout property's value from a given layer * @param {String} layer the layer to inspect * @param {String} name the name of the layout property * @returns {*} the property value * @private */ getLayoutProperty: function(layer, name) { return this.getReferentLayer(layer).getLayoutProperty(name); }, setPaintProperty: function(layer, name, value, klass) { this.getLayer(layer).setPaintProperty(name, value, klass); }, getPaintProperty: function(layer, name, klass) { return this.getLayer(layer).getPaintProperty(name, klass); }, featuresAt: function(coord, params, callback) { var features = []; var error = null; if (params.layer) { params.layer = { id: params.layer }; } util.asyncEach(Object.keys(this.sources), function(id, callback) { var source = this.sources[id]; source.featuresAt(coord, params, function(err, result) { if (result) features = features.concat(result); if (err) error = err; callback(); }); }.bind(this), function() { if (error) return callback(error); callback(null, features .filter(function(feature) { return this._layers[feature.layer] !== undefined; }.bind(this)) .map(function(feature) { feature.layer = this._layers[feature.layer].json(); return feature; }.bind(this))); }.bind(this)); }, _remove: function() { this.dispatcher.remove(); }, _updateSources: function(transform) { for (var id in this.sources) { this.sources[id].update(transform); } }, _redoPlacement: function() { for (var id in this.sources) { if (this.sources[id].redoPlacement) this.sources[id].redoPlacement(); } }, _forwardSourceEvent: function(e) { this.fire('source.' + e.type, util.extend({source: e.target}, e)); }, _forwardTileEvent: function(e) { this.fire(e.type, util.extend({source: e.target}, e)); }, // Callbacks from web workers 'get sprite json': function(params, callback) { var sprite = this.sprite; if (sprite.loaded()) { callback(null, { sprite: sprite.data, retina: sprite.retina }); } else { sprite.on('load', function() { callback(null, { sprite: sprite.data, retina: sprite.retina }); }); } }, 'get icons': function(params, callback) { var sprite = this.sprite; var spriteAtlas = this.spriteAtlas; if (sprite.loaded()) { spriteAtlas.setSprite(sprite); spriteAtlas.addIcons(params.icons, callback); } else { sprite.on('load', function() { spriteAtlas.setSprite(sprite); spriteAtlas.addIcons(params.icons, callback); }); } }, 'get glyphs': function(params, callback) { this.glyphSource.getSimpleGlyphs(params.fontstack, params.codepoints, params.uid, callback); } }); },{"../render/line_atlas":33,"../source/source":39,"../symbol/glyph_atlas":66,"../symbol/glyph_source":67,"../symbol/sprite_atlas":73,"../util/ajax":84,"../util/browser":85,"../util/dispatcher":87,"../util/evented":90,"../util/mapbox":93,"../util/util":96,"./animation_loop":47,"./image_sprite":48,"./style_layer":56,"mapbox-gl-style-spec/lib/validate/latest":106}],53:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); exports.resolve = function(value, constants) { function resolve(value) { return typeof value === 'string' && value[0] === '@' ? constants[value] : value; } var i; value = resolve(value); if (Array.isArray(value)) { value = value.slice(); for (i = 0; i < value.length; i++) { if (value[i] in constants) { value[i] = resolve(value[i]); } } } if (value.stops) { value = util.extend({}, value); value.stops = value.stops.slice(); for (i = 0; i < value.stops.length; i++) { if (value.stops[i][1] in constants) { value.stops[i] = [ value.stops[i][0], resolve(value.stops[i][1]) ]; } } } return value; }; exports.resolveAll = function (properties, constants) { if (!constants) return properties; var result = {}; for (var key in properties) { result[key] = exports.resolve(properties[key], constants); } return result; }; },{"../util/util":96}],54:[function(require,module,exports){ 'use strict'; var parseCSSColor = require('csscolorparser').parseCSSColor; var mapboxGLFunction = require('mapbox-gl-function'); var util = require('../util/util'); module.exports = StyleDeclaration; function StyleDeclaration(reference, value) { this.type = reference.type; this.transitionable = reference.transition; // immutable representation of value. used for comparison this.json = JSON.stringify(value); if (this.type !== 'color') { this.value = value; } else if (value.stops) { this.value = prepareColorFunction(value); } else { this.value = parseColor(value); } if (reference.function === 'interpolated') { this.calculate = mapboxGLFunction.interpolated(this.value); } else { this.calculate = mapboxGLFunction['piecewise-constant'](this.value); if (reference.transition) { this.calculate = transitioned(this.calculate); } } } function transitioned(calculate) { return function(z, zh, duration) { var fraction = z % 1; var t = Math.min((Date.now() - zh.lastIntegerZoomTime) / duration, 1); var fromScale = 1; var toScale = 1; var mix, from, to; if (z > zh.lastIntegerZoom) { mix = fraction + (1 - fraction) * t; fromScale *= 2; from = calculate(z - 1); to = calculate(z); } else { mix = 1 - (1 - t) * fraction; to = calculate(z); from = calculate(z + 1); fromScale /= 2; } return { from: from, fromScale: fromScale, to: to, toScale: toScale, t: mix }; }; } var colorCache = {}; function parseColor(value) { if (colorCache[value]) return colorCache[value]; var color = prepareColor(parseCSSColor(value)); colorCache[value] = color; return color; } function prepareColor(c) { return [c[0] / 255, c[1] / 255, c[2] / 255, c[3] / 1]; } function prepareColorFunction(f) { return util.extend({}, f, {stops: f.stops.map(function(stop) { return [stop[0], parseColor(stop[1])]; })}); } },{"../util/util":96,"csscolorparser":97,"mapbox-gl-function":105}],55:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var reference = require('./reference'); var StyleConstant = require('./style_constant'); var StyleDeclaration = require('./style_declaration'); var lookup = { paint: {}, layout: {} }; reference.layer.type.values.forEach(function(type) { lookup.paint[type] = makeConstructor(reference['paint_' + type]); lookup.layout[type] = makeConstructor(reference['layout_' + type]); }); function makeConstructor(reference) { function StyleDeclarationSet(properties, constants) { this._values = {}; this._transitions = {}; this._constants = constants; for (var k in properties) { this[k] = StyleConstant.resolve(properties[k], this._constants); } } Object.keys(reference).forEach(function(k) { var property = reference[k]; Object.defineProperty(StyleDeclarationSet.prototype, k, { set: function(v) { this._values[k] = new StyleDeclaration(property, StyleConstant.resolve(v, this._constants)); }, get: function() { return this._values[k].value; } }); if (property.transition) { Object.defineProperty(StyleDeclarationSet.prototype, k + '-transition', { set: function(v) { this._transitions[k] = v; }, get: function() { return this._transitions[k]; } }); } }); StyleDeclarationSet.prototype.values = function() { return this._values; }; StyleDeclarationSet.prototype.transition = function(k, global) { var t = this._transitions[k] || {}; return { duration: util.coalesce(t.duration, global.duration, 300), delay: util.coalesce(t.delay, global.delay, 0) }; }; StyleDeclarationSet.prototype.json = function() { var result = {}; for (var v in this._values) { result[v] = this._values[v].value; } for (var t in this._transitions) { result[t + '-transition'] = this._transitions[v]; } return result; }; return StyleDeclarationSet; } module.exports = function(renderType, layerType, properties, constants) { return new lookup[renderType][layerType](properties, constants); }; },{"../util/util":96,"./reference":51,"./style_constant":53,"./style_declaration":54}],56:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var StyleConstant = require('./style_constant'); var StyleTransition = require('./style_transition'); var StyleDeclarationSet = require('./style_declaration_set'); var LayoutProperties = require('./layout_properties'); var PaintProperties = require('./paint_properties'); module.exports = StyleLayer; function StyleLayer(layer, constants) { this._layer = layer; this._constants = constants; this.id = layer.id; this.ref = layer.ref; // Resolved and cascaded paint properties. this._resolved = {}; // class name -> StyleDeclarationSet this._cascaded = {}; // property name -> StyleTransition this.assign(layer); } StyleLayer.prototype = { resolveLayout: function() { if (!this.ref) { this.layout = new LayoutProperties[this.type]( StyleConstant.resolveAll(this._layer.layout, this._constants)); if (this.layout['symbol-placement'] === 'line') { if (!this.layout.hasOwnProperty('text-rotation-alignment')) { this.layout['text-rotation-alignment'] = 'map'; } if (!this.layout.hasOwnProperty('icon-rotation-alignment')) { this.layout['icon-rotation-alignment'] = 'map'; } this.layout['symbol-avoid-edges'] = true; } } }, setLayoutProperty: function(name, value) { this.layout[name] = StyleConstant.resolve(value, this._constants); }, getLayoutProperty: function(name) { return this.layout[name]; }, resolveReference: function(layers) { if (this.ref) { this.assign(layers[this.ref]); } }, resolvePaint: function() { for (var p in this._layer) { var match = p.match(/^paint(?:\.(.*))?$/); if (!match) continue; this._resolved[match[1] || ''] = new StyleDeclarationSet('paint', this.type, this._layer[p], this._constants); } }, setPaintProperty: function(name, value, klass) { var declarations = this._resolved[klass || '']; if (!declarations) { declarations = this._resolved[klass || ''] = new StyleDeclarationSet('paint', this.type, {}, this._constants); } declarations[name] = value; }, getPaintProperty: function(name, klass) { var declarations = this._resolved[klass || '']; if (!declarations) return undefined; return declarations[name]; }, cascade: function(classes, options, globalTrans, animationLoop) { for (var klass in this._resolved) { if (klass !== "" && !classes[klass]) continue; var declarations = this._resolved[klass], values = declarations.values(); for (var k in values) { var newDeclaration = values[k]; var oldTransition = options.transition ? this._cascaded[k] : undefined; // Only create a new transition if the declaration changed if (!oldTransition || oldTransition.declaration.json !== newDeclaration.json) { var newStyleTrans = declarations.transition(k, globalTrans); var newTransition = this._cascaded[k] = new StyleTransition(newDeclaration, oldTransition, newStyleTrans); // Run the animation loop until the end of the transition if (!newTransition.instant()) { newTransition.loopID = animationLoop.set(newTransition.endTime - (new Date()).getTime()); } if (oldTransition) { animationLoop.cancel(oldTransition.loopID); } } } } }, recalculate: function(z, zoomHistory) { var type = this.type, calculated = this.paint = new PaintProperties[type](); for (var k in this._cascaded) { calculated[k] = this._cascaded[k].at(z, zoomHistory); } this.hidden = (this.minzoom && z < this.minzoom) || (this.maxzoom && z >= this.maxzoom) || // include visibility check for non-bucketed background layers (this.layout.visibility === 'none'); if (type === 'symbol') { if ((calculated['text-opacity'] === 0 || !this.layout['text-field']) && (calculated['icon-opacity'] === 0 || !this.layout['icon-image'])) { this.hidden = true; } else { premultiplyLayer(calculated, 'text'); premultiplyLayer(calculated, 'icon'); } } else if (calculated[type + '-opacity'] === 0) { this.hidden = true; } else { premultiplyLayer(calculated, type); } if (this._cascaded['line-dasharray']) { // If the line is dashed, scale the dash lengths by the line // width at the previous round zoom level. var dashArray = calculated['line-dasharray']; var lineWidth = this._cascaded['line-width'] ? this._cascaded['line-width'].at(Math.floor(z), Infinity) : calculated['line-width']; dashArray.fromScale *= lineWidth; dashArray.toScale *= lineWidth; } return !this.hidden; }, assign: function(layer) { util.extend(this, util.pick(layer, ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout'])); }, json: function() { return util.extend({}, this._layer, util.pick(this, ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout', 'paint'])); } }; function premultiplyLayer(layer, type) { var colorProp = type + '-color', haloProp = type + '-halo-color', outlineProp = type + '-outline-color', color = layer[colorProp], haloColor = layer[haloProp], outlineColor = layer[outlineProp], opacity = layer[type + '-opacity']; var colorOpacity = color && (opacity * color[3]); var haloOpacity = haloColor && (opacity * haloColor[3]); var outlineOpacity = outlineColor && (opacity * outlineColor[3]); if (colorOpacity !== undefined && colorOpacity < 1) { layer[colorProp] = util.premultiply([color[0], color[1], color[2], colorOpacity]); } if (haloOpacity !== undefined && haloOpacity < 1) { layer[haloProp] = util.premultiply([haloColor[0], haloColor[1], haloColor[2], haloOpacity]); } if (outlineOpacity !== undefined && outlineOpacity < 1) { layer[outlineProp] = util.premultiply([outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity]); } } },{"../util/util":96,"./layout_properties":49,"./paint_properties":50,"./style_constant":53,"./style_declaration_set":55,"./style_transition":57}],57:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var interpolate = require('../util/interpolate'); module.exports = StyleTransition; /* * Represents a transition between two declarations */ function StyleTransition(declaration, oldTransition, value) { this.declaration = declaration; this.startTime = this.endTime = (new Date()).getTime(); var type = declaration.type; if ((type === 'string' || type === 'array') && declaration.transitionable) { this.interp = interpZoomTransitioned; } else { this.interp = interpolate[type]; } this.oldTransition = oldTransition; this.duration = value.duration || 0; this.delay = value.delay || 0; if (!this.instant()) { this.endTime = this.startTime + this.duration + this.delay; this.ease = util.easeCubicInOut; } if (oldTransition && oldTransition.endTime <= this.startTime) { // Old transition is done running, so we can // delete its reference to its old transition. delete oldTransition.oldTransition; } } StyleTransition.prototype.instant = function() { return !this.oldTransition || !this.interp || (this.duration === 0 && this.delay === 0); }; /* * Return the value of the transitioning property at zoom level `z` and optional time `t` */ StyleTransition.prototype.at = function(z, zoomHistory, t) { var value = this.declaration.calculate(z, zoomHistory, this.duration); if (this.instant()) return value; t = t || Date.now(); if (t < this.endTime) { var oldValue = this.oldTransition.at(z, zoomHistory, this.startTime); var eased = this.ease((t - this.startTime - this.delay) / this.duration); value = this.interp(oldValue, value, eased); } return value; }; function interpZoomTransitioned(from, to, t) { return { from: from.to, fromScale: from.toScale, to: to.to, toScale: to.toScale, t: t }; } },{"../util/interpolate":92,"../util/util":96}],58:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = Anchor; function Anchor(x, y, angle, segment) { this.x = x; this.y = y; this.angle = angle; if (segment !== undefined) { this.segment = segment; } } Anchor.prototype = Object.create(Point.prototype); Anchor.prototype.clone = function() { return new Anchor(this.x, this.y, this.angle, this.segment); }; },{"point-geometry":113}],59:[function(require,module,exports){ 'use strict'; module.exports = BinPack; function BinPack(width, height) { this.width = width; this.height = height; this.free = [{ x: 0, y: 0, w: width, h: height }]; } /** * Simple algorithm to recursively merge the newly released cell with its * neighbor. This doesn't merge more than two cells at a time, and fails * for complicated merges. * @private */ BinPack.prototype.release = function(rect) { for (var i = 0; i < this.free.length; i++) { var free = this.free[i]; if (free.y === rect.y && free.h === rect.h && free.x + free.w === rect.x) { free.w += rect.w; } else if (free.x === rect.x && free.w === rect.w && free.y + free.h === rect.y) { free.h += rect.h; } else if (rect.y === free.y && rect.h === free.h && rect.x + rect.w === free.x) { free.x = rect.x; free.w += rect.w; } else if (rect.x === free.x && rect.w === free.w && rect.y + rect.h === free.y) { free.y = rect.y; free.h += rect.h; } else continue; this.free.splice(i, 1); this.release(free); return; } this.free.push(rect); }; BinPack.prototype.allocate = function(width, height) { // Find the smallest free rect angle var rect = { x: Infinity, y: Infinity, w: Infinity, h: Infinity }; var smallest = -1; for (var i = 0; i < this.free.length; i++) { var ref = this.free[i]; if (width <= ref.w && height <= ref.h && ref.y <= rect.y && ref.x <= rect.x) { rect = ref; smallest = i; } } if (smallest < 0) { // There's no space left for this char. return { x: -1, y: -1 }; } this.free.splice(smallest, 1); // Shorter/Longer Axis Split Rule (SAS) // http://clb.demon.fi/files/RectangleBinPack.pdf p. 15 // Ignore the dimension of R and just split long the shorter dimension // See Also: http://www.cs.princeton.edu/~chazelle/pubs/blbinpacking.pdf if (rect.w < rect.h) { // split horizontally // +--+---+ // |__|___| <-- b1 // +------+ <-- b2 if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: height }); if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: rect.w, h: rect.h - height }); } else { // split vertically // +--+---+ // |__| | <-- b1 // +--|---+ <-- b2 if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: rect.h }); if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: width, h: rect.h - height }); } return { x: rect.x, y: rect.y, w: width, h: height }; }; },{}],60:[function(require,module,exports){ 'use strict'; module.exports = checkMaxAngle; function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) { // horizontal labels always pass if (anchor.segment === undefined) return true; var p = anchor; var index = anchor.segment + 1; var anchorDistance = 0; // move backwards along the line to the first segment the label appears on while (anchorDistance > -labelLength / 2) { index--; // there isn't enough room for the label after the beginning of the line if (index < 0) return false; anchorDistance -= line[index].dist(p); p = line[index]; } anchorDistance += line[index].dist(line[index + 1]); index++; // store recent corners and their total angle difference var recentCorners = []; var recentAngleDelta = 0; // move forwards by the length of the label and check angles along the way while (anchorDistance < labelLength / 2) { var prev = line[index - 1]; var current = line[index]; var next = line[index + 1]; // there isn't enough room for the label before the end of the line if (!next) return false; var angleDelta = prev.angleTo(current) - current.angleTo(next); // restrict angle to -pi..pi range angleDelta = ((angleDelta + 3 * Math.PI) % (Math.PI * 2)) - Math.PI; recentCorners.push({ distance: anchorDistance, angleDelta: angleDelta }); recentAngleDelta += angleDelta; // remove corners that are far enough away from the list of recent anchors while (anchorDistance - recentCorners[0].distance > windowSize) { recentAngleDelta -= recentCorners.shift().angleDelta; } // the sum of angles within the window area exceeds the maximum allowed value. check fails. if (Math.abs(recentAngleDelta) > maxAngle) return false; index++; anchorDistance += current.dist(next); } // no part of the line had an angle greater than the maximum allowed. check passes. return true; } },{}],61:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = clipLine; function clipLine(lines, x1, y1, x2, y2) { var clippedLines = []; for (var l = 0; l < lines.length; l++) { var line = lines[l]; var clippedLine; for (var i = 0; i < line.length - 1; i++) { var p0 = line[i]; var p1 = line[i + 1]; if (p0.x < x1 && p1.x < x1) { continue; } else if (p0.x < x1) { p0 = new Point(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x))); } else if (p1.x < x1) { p1 = new Point(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x))); } if (p0.y < y1 && p1.y < y1) { continue; } else if (p0.y < y1) { p0 = new Point(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1); } else if (p1.y < y1) { p1 = new Point(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1); } if (p0.x >= x2 && p1.x >= x2) { continue; } else if (p0.x >= x2) { p0 = new Point(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x))); } else if (p1.x >= x2) { p1 = new Point(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x))); } if (p0.y >= y2 && p1.y >= y2) { continue; } else if (p0.y >= y2) { p0 = new Point(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2); } else if (p1.y >= y2) { p1 = new Point(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2); } if (!clippedLine || !p0.equals(clippedLine[clippedLine.length - 1])) { clippedLine = [p0]; clippedLines.push(clippedLine); } clippedLine.push(p1); } } return clippedLines; } },{"point-geometry":113}],62:[function(require,module,exports){ 'use strict'; module.exports = CollisionBox; function CollisionBox(anchor, x1, y1, x2, y2, maxScale) { // the box is centered around the anchor point this.anchor = anchor; // distances to the edges from the anchor this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; // the box is only valid for scales < maxScale. // The box does not block other boxes at scales >= maxScale; this.maxScale = maxScale; // the scale at which the label can first be shown this.placementScale = 0; // rotated and scaled bbox used for indexing this[0] = this[1] = this[2] = this[3] = 0; } },{}],63:[function(require,module,exports){ 'use strict'; var CollisionBox = require('./collision_box'); module.exports = CollisionFeature; function CollisionFeature(line, anchor, shaped, boxScale, padding, alignLine) { var y1 = shaped.top * boxScale - padding; var y2 = shaped.bottom * boxScale + padding; var x1 = shaped.left * boxScale - padding; var x2 = shaped.right * boxScale + padding; this.boxes = []; if (alignLine) { var height = y2 - y1; var length = x2 - x1; if (height <= 0) return; // set minimum box height to avoid very many small labels height = Math.max(10 * boxScale, height); this.bboxifyLabel(line, anchor, length, height); } else { this.boxes.push(new CollisionBox(anchor, x1, y1, x2, y2, Infinity)); } } CollisionFeature.prototype.bboxifyLabel = function(line, anchor, labelLength, boxSize) { var step = boxSize / 2; var nBoxes = Math.floor(labelLength / step); // offset the center of the first box by half a box so that the edge of the // box is at the edge of the label. var firstBoxOffset = -boxSize / 2; var bboxes = this.boxes; var p = anchor; var index = anchor.segment + 1; var anchorDistance = firstBoxOffset; // move backwards along the line to the first segment the label appears on do { index--; // there isn't enough room for the label after the beginning of the line // checkMaxAngle should have already caught this if (index < 0) return bboxes; anchorDistance -= line[index].dist(p); p = line[index]; } while (anchorDistance > -labelLength / 2); var segmentLength = line[index].dist(line[index + 1]); for (var i = 0; i < nBoxes; i++) { // the distance the box will be from the anchor var boxDistanceToAnchor = -labelLength / 2 + i * step; // the box is not on the current segment. Move to the next segment. while (anchorDistance + segmentLength < boxDistanceToAnchor) { anchorDistance += segmentLength; index++; // There isn't enough room before the end of the line. if (index + 1 >= line.length) return bboxes; segmentLength = line[index].dist(line[index + 1]); } // the distance the box will be from the beginning of the segment var segmentBoxDistance = boxDistanceToAnchor - anchorDistance; var p0 = line[index]; var p1 = line[index + 1]; var boxAnchor = p1.sub(p0)._unit()._mult(segmentBoxDistance)._add(p0); var distanceToInnerEdge = Math.max(Math.abs(boxDistanceToAnchor - firstBoxOffset) - step / 2, 0); var maxScale = labelLength / 2 / distanceToInnerEdge; bboxes.push(new CollisionBox(boxAnchor, -boxSize / 2, -boxSize / 2, boxSize / 2, boxSize / 2, maxScale)); } return bboxes; }; },{"./collision_box":62}],64:[function(require,module,exports){ 'use strict'; var rbush = require('rbush'); module.exports = CollisionTile; function CollisionTile(zoom, tileExtent, tileSize) { this.zoom = zoom; this.tilePixelRatio = tileExtent / tileSize; } CollisionTile.prototype.minScale = 0.25; CollisionTile.prototype.maxScale = 2; CollisionTile.prototype.reset = function(angle, pitch) { this.tree = rbush(); this.angle = angle; var sin = Math.sin(angle), cos = Math.cos(angle); this.rotationMatrix = [cos, -sin, sin, cos]; // Stretch boxes in y direction to account for the map tilt. this.yStretch = 1 / Math.cos(pitch / 180 * Math.PI); // The amount the map is squished depends on the y position. // Sort of account for this by making all boxes a bit bigger. this.yStretch = Math.pow(this.yStretch, 1.3); }; CollisionTile.prototype.placeFeature = function(feature) { var minPlacementScale = this.minScale; var rotationMatrix = this.rotationMatrix; var yStretch = this.yStretch; for (var b = 0; b < feature.boxes.length; b++) { var box = feature.boxes[b]; var anchor = box.anchor.matMult(rotationMatrix); var x = anchor.x; var y = anchor.y; box[0] = x + box.x1; box[1] = y + box.y1 * yStretch; box[2] = x + box.x2; box[3] = y + box.y2 * yStretch; var blockingBoxes = this.tree.search(box); for (var i = 0; i < blockingBoxes.length; i++) { var blocking = blockingBoxes[i]; var blockingAnchor = blocking.anchor.matMult(rotationMatrix); // Find the lowest scale at which the two boxes can fit side by side without overlapping. // Original algorithm: var s1 = (blocking.x1 - box.x2) / (x - blockingAnchor.x); // scale at which new box is to the left of old box var s2 = (blocking.x2 - box.x1) / (x - blockingAnchor.x); // scale at which new box is to the right of old box var s3 = (blocking.y1 - box.y2) * yStretch / (y - blockingAnchor.y); // scale at which new box is to the top of old box var s4 = (blocking.y2 - box.y1) * yStretch / (y - blockingAnchor.y); // scale at which new box is to the bottom of old box if (isNaN(s1) || isNaN(s2)) s1 = s2 = 1; if (isNaN(s3) || isNaN(s4)) s3 = s4 = 1; var collisionFreeScale = Math.min(Math.max(s1, s2), Math.max(s3, s4)); if (collisionFreeScale > blocking.maxScale) { // After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it, // so unblock the new box at the scale that the old box disappears. collisionFreeScale = blocking.maxScale; } if (collisionFreeScale > box.maxScale) { // If the box can only be shown after it is visible, then the box can never be shown. // But the label can be shown after this box is not visible. collisionFreeScale = box.maxScale; } if (collisionFreeScale > minPlacementScale && collisionFreeScale >= blocking.placementScale) { // If this collision occurs at a lower scale than previously found collisions // and the collision occurs while the other label is visible // this this is the lowest scale at which the label won't collide with anything minPlacementScale = collisionFreeScale; } if (minPlacementScale >= this.maxScale) return minPlacementScale; } } return minPlacementScale; }; CollisionTile.prototype.insertFeature = function(feature, minPlacementScale) { var boxes = feature.boxes; for (var k = 0; k < boxes.length; k++) { boxes[k].placementScale = minPlacementScale; } if (minPlacementScale < this.maxScale) { this.tree.load(boxes); } }; },{"rbush":114}],65:[function(require,module,exports){ 'use strict'; var interpolate = require('../util/interpolate'); var Anchor = require('../symbol/anchor'); var checkMaxAngle = require('./check_max_angle'); module.exports = getAnchors; function getAnchors(line, spacing, maxAngle, shapedText, glyphSize, boxScale, overscaling) { // Resample a line to get anchor points for labels and check that each // potential label passes text-max-angle check and has enough froom to fit // on the line. var angleWindowSize = shapedText ? 3 / 5 * glyphSize * boxScale : 0; // Offset the first anchor by half the label length (or half the spacing distance for icons). // Add a bit of extra offset to avoid collisions at T intersections. var labelLength = shapedText ? shapedText.right - shapedText.left : spacing; var extraOffset = glyphSize * 2; var offset = ((labelLength / 2 + extraOffset) * boxScale * overscaling) % spacing; return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength * boxScale, false); } function resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength, placeAtMiddle) { var distance = 0, markedDistance = offset ? offset - spacing : 0; var anchors = []; for (var i = 0; i < line.length - 1; i++) { var a = line[i], b = line[i + 1]; var segmentDist = a.dist(b), angle = b.angleTo(a); while (markedDistance + spacing < distance + segmentDist) { markedDistance += spacing; var t = (markedDistance - distance) / segmentDist, x = interpolate(a.x, b.x, t), y = interpolate(a.y, b.y, t); if (x >= 0 && x < 4096 && y >= 0 && y < 4096) { x = Math.round(x); y = Math.round(y); var anchor = new Anchor(x, y, angle, i); if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) { anchors.push(anchor); } } } distance += segmentDist; } if (!placeAtMiddle && !anchors.length) { // The first attempt at finding anchors at which labels can be placed failed. // Try again, but this time just try placing one anchor at the middle of the line. // This has the most effect for short lines in overscaled tiles, since the // initial offset used in overscaled tiles is calculated to align labels with positions in // parent tiles instead of placing the label as close to the beginning as possible. anchors = resample(line, distance / 2, spacing, angleWindowSize, maxAngle, labelLength, true); } return anchors; } },{"../symbol/anchor":58,"../util/interpolate":92,"./check_max_angle":60}],66:[function(require,module,exports){ 'use strict'; var BinPack = require('./bin_pack'); module.exports = GlyphAtlas; function GlyphAtlas(width, height) { this.width = width; this.height = height; this.bin = new BinPack(width, height); this.index = {}; this.ids = {}; this.data = new Uint8Array(width * height); } GlyphAtlas.prototype = { get debug() { return 'canvas' in this; }, set debug(value) { if (value && !this.canvas) { this.canvas = document.createElement('canvas'); this.canvas.width = this.width; this.canvas.height = this.height; document.body.appendChild(this.canvas); this.ctx = this.canvas.getContext('2d'); } else if (!value && this.canvas) { this.canvas.parentNode.removeChild(this.canvas); delete this.ctx; delete this.canvas; } } }; GlyphAtlas.prototype.getGlyphs = function() { var glyphs = {}, split, name, id; for (var key in this.ids) { split = key.split('#'); name = split[0]; id = split[1]; if (!glyphs[name]) glyphs[name] = []; glyphs[name].push(id); } return glyphs; }; GlyphAtlas.prototype.getRects = function() { var rects = {}, split, name, id; for (var key in this.ids) { split = key.split('#'); name = split[0]; id = split[1]; if (!rects[name]) rects[name] = {}; rects[name][id] = this.index[key]; } return rects; }; GlyphAtlas.prototype.removeGlyphs = function(id) { for (var key in this.ids) { var ids = this.ids[key]; var pos = ids.indexOf(id); if (pos >= 0) ids.splice(pos, 1); this.ids[key] = ids; if (!ids.length) { var rect = this.index[key]; var target = this.data; for (var y = 0; y < rect.h; y++) { var y1 = this.width * (rect.y + y) + rect.x; for (var x = 0; x < rect.w; x++) { target[y1 + x] = 0; } } this.dirty = true; this.bin.release(rect); delete this.index[key]; delete this.ids[key]; } } this.updateTexture(this.gl); }; GlyphAtlas.prototype.addGlyph = function(id, name, glyph, buffer) { if (!glyph) { // console.warn('missing glyph', code, String.fromCharCode(code)); return null; } var key = name + "#" + glyph.id; // The glyph is already in this texture. if (this.index[key]) { if (this.ids[key].indexOf(id) < 0) { this.ids[key].push(id); } return this.index[key]; } // The glyph bitmap has zero width. if (!glyph.bitmap) { return null; } var bufferedWidth = glyph.width + buffer * 2; var bufferedHeight = glyph.height + buffer * 2; // Add a 1px border around every image. var padding = 1; var packWidth = bufferedWidth + 2 * padding; var packHeight = bufferedHeight + 2 * padding; // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them // into 2 bytes rather than 4 bytes. packWidth += (4 - packWidth % 4); packHeight += (4 - packHeight % 4); var rect = this.bin.allocate(packWidth, packHeight); if (rect.x < 0) { console.warn('glyph bitmap overflow'); return { glyph: glyph, rect: null }; } this.index[key] = rect; this.ids[key] = [id]; var target = this.data; var source = glyph.bitmap; for (var y = 0; y < bufferedHeight; y++) { var y1 = this.width * (rect.y + y + padding) + rect.x + padding; var y2 = bufferedWidth * y; for (var x = 0; x < bufferedWidth; x++) { target[y1 + x] = source[y2 + x]; } } this.dirty = true; return rect; }; GlyphAtlas.prototype.bind = function(gl) { this.gl = gl; if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, this.width, this.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null); } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } }; GlyphAtlas.prototype.updateTexture = function(gl) { this.bind(gl); if (this.dirty) { gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.ALPHA, gl.UNSIGNED_BYTE, this.data); // DEBUG if (this.ctx) { var data = this.ctx.getImageData(0, 0, this.width, this.height); for (var i = 0, j = 0; i < this.data.length; i++, j += 4) { data.data[j] = this.data[i]; data.data[j + 1] = this.data[i]; data.data[j + 2] = this.data[i]; data.data[j + 3] = 255; } this.ctx.putImageData(data, 0, 0); this.ctx.strokeStyle = 'red'; for (var k = 0; k < this.bin.free.length; k++) { var free = this.bin.free[k]; this.ctx.strokeRect(free.x, free.y, free.w, free.h); } } // END DEBUG this.dirty = false; } }; },{"./bin_pack":59}],67:[function(require,module,exports){ 'use strict'; var normalizeURL = require('../util/mapbox').normalizeGlyphsURL; var getArrayBuffer = require('../util/ajax').getArrayBuffer; var Glyphs = require('../util/glyphs'); var Protobuf = require('pbf'); module.exports = GlyphSource; /** * A glyph source has a URL from which to load new glyphs and owns a GlyphAtlas * that stores currently-loaded glyphs. * * @param {string} url glyph template url * @param {Object} glyphAtlas glyph atlas object * @private */ function GlyphSource(url, glyphAtlas) { this.url = url && normalizeURL(url); this.glyphAtlas = glyphAtlas; this.stacks = []; this.loading = {}; } GlyphSource.prototype.getSimpleGlyphs = function(fontstack, glyphIDs, uid, callback) { if (this.stacks[fontstack] === undefined) this.stacks[fontstack] = {}; var glyphs = {}; var stack = this.stacks[fontstack]; var glyphAtlas = this.glyphAtlas; // the number of pixels the sdf bitmaps are padded by var buffer = 3; var missing = {}; var remaining = 0; var range; for (var i = 0; i < glyphIDs.length; i++) { var glyphID = glyphIDs[i]; range = Math.floor(glyphID / 256); if (stack[range]) { var glyph = stack[range].glyphs[glyphID]; var rect = glyphAtlas.addGlyph(uid, fontstack, glyph, buffer); if (glyph) glyphs[glyphID] = new SimpleGlyph(glyph, rect, buffer); } else { if (missing[range] === undefined) { missing[range] = []; remaining++; } missing[range].push(glyphID); } } if (!remaining) callback(undefined, glyphs); var onRangeLoaded = function(err, range, data) { // TODO not be silent about errors if (!err) { var stack = this.stacks[fontstack][range] = data.stacks[0]; for (var i = 0; i < missing[range].length; i++) { var glyphID = missing[range][i]; var glyph = stack.glyphs[glyphID]; var rect = glyphAtlas.addGlyph(uid, fontstack, glyph, buffer); if (glyph) glyphs[glyphID] = new SimpleGlyph(glyph, rect, buffer); } } remaining--; if (!remaining) callback(undefined, glyphs); }.bind(this); for (var r in missing) { this.loadRange(fontstack, r, onRangeLoaded); } }; // A simplified representation of the glyph containing only the properties needed for shaping. function SimpleGlyph(glyph, rect, buffer) { var padding = 1; this.advance = glyph.advance; this.left = glyph.left - buffer - padding; this.top = glyph.top + buffer + padding; this.rect = rect; } GlyphSource.prototype.loadRange = function(fontstack, range, callback) { if (range * 256 > 65535) return callback('gyphs > 65535 not supported'); if (this.loading[fontstack] === undefined) this.loading[fontstack] = {}; var loading = this.loading[fontstack]; if (loading[range]) { loading[range].push(callback); } else { loading[range] = [callback]; var rangeName = (range * 256) + '-' + (range * 256 + 255); var url = glyphUrl(fontstack, rangeName, this.url); getArrayBuffer(url, function(err, data) { var glyphs = !err && new Glyphs(new Protobuf(new Uint8Array(data))); for (var i = 0; i < loading[range].length; i++) { loading[range][i](err, range, glyphs); } delete loading[range]; }); } }; /** * Use CNAME sharding to load a specific glyph range over a randomized * but consistent subdomain. * @param {string} fontstack comma-joined fonts * @param {string} range comma-joined range * @param {url} url templated url * @param {string} [subdomains=abc] subdomains as a string where each letter is one. * @returns {string} a url to load that section of glyphs * @private */ function glyphUrl(fontstack, range, url, subdomains) { subdomains = subdomains || 'abc'; return url .replace('{s}', subdomains[fontstack.length % subdomains.length]) .replace('{fontstack}', fontstack) .replace('{range}', range); } },{"../util/ajax":84,"../util/glyphs":91,"../util/mapbox":93,"pbf":111}],68:[function(require,module,exports){ 'use strict'; module.exports = function (features, textFeatures, geometries) { var leftIndex = {}, rightIndex = {}, mergedFeatures = [], mergedGeom = [], mergedTexts = [], mergedIndex = 0, k; function add(k) { mergedFeatures.push(features[k]); mergedGeom.push(geometries[k]); mergedTexts.push(textFeatures[k]); mergedIndex++; } function mergeFromRight(leftKey, rightKey, geom) { var i = rightIndex[leftKey]; delete rightIndex[leftKey]; rightIndex[rightKey] = i; mergedGeom[i][0].pop(); mergedGeom[i][0] = mergedGeom[i][0].concat(geom[0]); return i; } function mergeFromLeft(leftKey, rightKey, geom) { var i = leftIndex[rightKey]; delete leftIndex[rightKey]; leftIndex[leftKey] = i; mergedGeom[i][0].shift(); mergedGeom[i][0] = geom[0].concat(mergedGeom[i][0]); return i; } function getKey(text, geom, onRight) { var point = onRight ? geom[0][geom[0].length - 1] : geom[0][0]; return text + ':' + point.x + ':' + point.y; } for (k = 0; k < features.length; k++) { var geom = geometries[k], text = textFeatures[k]; if (!text) { add(k); continue; } var leftKey = getKey(text, geom), rightKey = getKey(text, geom, true); if ((leftKey in rightIndex) && (rightKey in leftIndex) && (rightIndex[leftKey] !== leftIndex[rightKey])) { // found lines with the same text adjacent to both ends of the current line, merge all three var j = mergeFromLeft(leftKey, rightKey, geom); var i = mergeFromRight(leftKey, rightKey, mergedGeom[j]); delete leftIndex[leftKey]; delete rightIndex[rightKey]; rightIndex[getKey(text, mergedGeom[i], true)] = i; mergedGeom[j] = null; } else if (leftKey in rightIndex) { // found mergeable line adjacent to the start of the current line, merge mergeFromRight(leftKey, rightKey, geom); } else if (rightKey in leftIndex) { // found mergeable line adjacent to the end of the current line, merge mergeFromLeft(leftKey, rightKey, geom); } else { // no adjacent lines, add as a new item add(k); leftIndex[leftKey] = mergedIndex - 1; rightIndex[rightKey] = mergedIndex - 1; } } return { features: mergedFeatures, textFeatures: mergedTexts, geometries: mergedGeom }; }; },{}],69:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); var Anchor = require('../symbol/anchor'); module.exports = { getIconQuads: getIconQuads, getGlyphQuads: getGlyphQuads }; var minScale = 0.5; // underscale by 1 zoom level function SymbolQuad(anchor, tl, tr, bl, br, tex, angle, minScale, maxScale) { this.anchor = anchor; this.tl = tl; this.tr = tr; this.bl = bl; this.br = br; this.tex = tex; this.angle = angle; this.minScale = minScale; this.maxScale = maxScale; } function getIconQuads(anchor, shapedIcon, boxScale, line, layout, alongLine) { var rect = shapedIcon.image.rect; var border = 1; var left = shapedIcon.left - border; var right = left + rect.w; var top = shapedIcon.top - border; var bottom = top + rect.h; var tl = new Point(left, top); var tr = new Point(right, top); var br = new Point(right, bottom); var bl = new Point(left, bottom); var angle = layout['icon-rotate'] * Math.PI / 180; if (alongLine) { var prev = line[anchor.segment]; angle += Math.atan2(anchor.y - prev.y, anchor.x - prev.x); } if (angle) { var sin = Math.sin(angle), cos = Math.cos(angle), matrix = [cos, -sin, sin, cos]; tl = tl.matMult(matrix); tr = tr.matMult(matrix); bl = bl.matMult(matrix); br = br.matMult(matrix); } return [new SymbolQuad(anchor, tl, tr, bl, br, shapedIcon.image.rect, 0, minScale, Infinity)]; } function getGlyphQuads(anchor, shaping, boxScale, line, layout, alongLine) { var textRotate = layout['text-rotate'] * Math.PI / 180; var keepUpright = layout['text-keep-upright']; var positionedGlyphs = shaping.positionedGlyphs; var quads = []; for (var k = 0; k < positionedGlyphs.length; k++) { var positionedGlyph = positionedGlyphs[k]; var glyph = positionedGlyph.glyph; var rect = glyph.rect; if (!rect) continue; var centerX = (positionedGlyph.x + glyph.advance / 2) * boxScale; var glyphInstances; var labelMinScale = minScale; if (alongLine) { glyphInstances = []; labelMinScale = getSegmentGlyphs(glyphInstances, anchor, centerX, line, anchor.segment, 1); if (keepUpright) { labelMinScale = Math.min(labelMinScale, getSegmentGlyphs(glyphInstances, anchor, centerX, line, anchor.segment, -1)); } } else { glyphInstances = [{ anchor: anchor, offset: 0, angle: 0, maxScale: Infinity, minScale: minScale }]; } var x1 = positionedGlyph.x + glyph.left, y1 = positionedGlyph.y - glyph.top, x2 = x1 + rect.w, y2 = y1 + rect.h, otl = new Point(x1, y1), otr = new Point(x2, y1), obl = new Point(x1, y2), obr = new Point(x2, y2); for (var i = 0; i < glyphInstances.length; i++) { var instance = glyphInstances[i], tl = otl, tr = otr, bl = obl, br = obr, angle = instance.angle + textRotate; if (angle) { var sin = Math.sin(angle), cos = Math.cos(angle), matrix = [cos, -sin, sin, cos]; tl = tl.matMult(matrix); tr = tr.matMult(matrix); bl = bl.matMult(matrix); br = br.matMult(matrix); } // Prevent label from extending past the end of the line var glyphMinScale = Math.max(instance.minScale, labelMinScale); var glyphAngle = (anchor.angle + textRotate + instance.offset + 2 * Math.PI) % (2 * Math.PI); quads.push(new SymbolQuad(instance.anchor, tl, tr, bl, br, rect, glyphAngle, glyphMinScale, instance.maxScale)); } } return quads; } function getSegmentGlyphs(glyphs, anchor, offset, line, segment, direction) { var upsideDown = direction < 0; if (offset < 0) direction *= -1; if (direction > 0) segment++; var newAnchor = anchor; var end = line[segment]; var prevScale = Infinity; offset = Math.abs(offset); var placementScale = minScale; while (true) { var distance = newAnchor.dist(end); var scale = offset / distance; // Get the angle of the line segment var angle = Math.atan2(end.y - newAnchor.y, end.x - newAnchor.x); if (direction < 0) angle += Math.PI; if (upsideDown) angle += Math.PI; glyphs.push({ anchor: new Anchor(newAnchor.x, newAnchor.y, anchor.angle), offset: upsideDown ? Math.PI : 0, minScale: scale, maxScale: prevScale, angle: (angle + 2 * Math.PI) % (2 * Math.PI) }); if (scale <= placementScale) break; newAnchor = end; // skip duplicate nodes while (newAnchor.equals(end)) { segment += direction; end = line[segment]; if (!end) { return scale; } } var unit = end.sub(newAnchor)._unit(); newAnchor = newAnchor.sub(unit._mult(distance)); prevScale = scale; } return placementScale; } },{"../symbol/anchor":58,"point-geometry":113}],70:[function(require,module,exports){ 'use strict'; var resolveTokens = require('../util/token'); module.exports = resolveIcons; // For an array of features determine what icons need to be loaded. function resolveIcons(features, layoutProperties) { var icons = []; for (var i = 0, fl = features.length; i < fl; i++) { var text = resolveTokens(features[i].properties, layoutProperties['icon-image']); if (!text) continue; if (icons.indexOf(text) < 0) { icons.push(text); } } return icons; } },{"../util/token":95}],71:[function(require,module,exports){ 'use strict'; var resolveTokens = require('../util/token'); module.exports = resolveText; /** * For an array of features determine what glyph ranges need to be loaded * and apply any text preprocessing. The remaining users of text should * use the `textFeatures` key returned by this function rather than accessing * feature text directly. * @private */ function resolveText(features, layoutProperties, glyphs) { var textFeatures = []; var codepoints = []; for (var i = 0, fl = features.length; i < fl; i++) { var text = resolveTokens(features[i].properties, layoutProperties['text-field']); if (!text) { textFeatures[i] = null; continue; } text = text.toString(); var transform = layoutProperties['text-transform']; if (transform === 'uppercase') { text = text.toLocaleUpperCase(); } else if (transform === 'lowercase') { text = text.toLocaleLowerCase(); } for (var j = 0, jl = text.length; j < jl; j++) { codepoints.push(text.charCodeAt(j)); } // Track indexes of features with text. textFeatures[i] = text; } // get a list of unique codepoints we are missing codepoints = uniq(codepoints, glyphs); return { textFeatures: textFeatures, codepoints: codepoints }; } function uniq(ids, alreadyHave) { var u = []; var last; ids.sort(sortNumbers); for (var i = 0; i < ids.length; i++) { if (ids[i] !== last) { last = ids[i]; if (!alreadyHave[last]) u.push(ids[i]); } } return u; } function sortNumbers(a, b) { return a - b; } },{"../util/token":95}],72:[function(require,module,exports){ 'use strict'; module.exports = { shapeText: shapeText, shapeIcon: shapeIcon }; // The position of a glyph relative to the text's anchor point. function PositionedGlyph(codePoint, x, y, glyph) { this.codePoint = codePoint; this.x = x; this.y = y; this.glyph = glyph; } // A collection of positioned glyphs and some metadata function Shaping(positionedGlyphs, top, bottom, left, right) { this.positionedGlyphs = positionedGlyphs; this.top = top; this.bottom = bottom; this.left = left; this.right = right; } function shapeText(text, glyphs, maxWidth, lineHeight, horizontalAlign, verticalAlign, justify, spacing, translate) { var positionedGlyphs = []; var shaping = new Shaping(positionedGlyphs, translate[1], translate[1], translate[0], translate[0]); // the y offset *should* be part of the font metadata var yOffset = -17; var x = translate[0]; var y = translate[1] + yOffset; for (var i = 0; i < text.length; i++) { var codePoint = text.charCodeAt(i); var glyph = glyphs[codePoint]; if (!glyph) continue; positionedGlyphs.push(new PositionedGlyph(codePoint, x, y, glyph)); x += glyph.advance + spacing; } if (!positionedGlyphs.length) return false; linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify); return shaping; } var breakable = { 32: true }; // Currently only breaks at regular spaces function linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify) { var lastSafeBreak = null; var lengthBeforeCurrentLine = 0; var lineStartIndex = 0; var line = 0; var maxLineLength = 0; var positionedGlyphs = shaping.positionedGlyphs; if (maxWidth) { for (var i = 0; i < positionedGlyphs.length; i++) { var positionedGlyph = positionedGlyphs[i]; positionedGlyph.x -= lengthBeforeCurrentLine; positionedGlyph.y += lineHeight * line; if (positionedGlyph.x > maxWidth && lastSafeBreak !== null) { var lineLength = positionedGlyphs[lastSafeBreak + 1].x; maxLineLength = Math.max(lineLength, maxLineLength); for (var k = lastSafeBreak + 1; k <= i; k++) { positionedGlyphs[k].y += lineHeight; positionedGlyphs[k].x -= lineLength; } if (justify) { justifyLine(positionedGlyphs, glyphs, lineStartIndex, lastSafeBreak - 1, justify); } lineStartIndex = lastSafeBreak + 1; lastSafeBreak = null; lengthBeforeCurrentLine += lineLength; line++; } if (breakable[positionedGlyph.codePoint]) { lastSafeBreak = i; } } } var lastPositionedGlyph = positionedGlyphs[positionedGlyphs.length - 1]; var lastLineLength = lastPositionedGlyph.x + glyphs[lastPositionedGlyph.codePoint].advance; maxLineLength = Math.max(maxLineLength, lastLineLength); var height = (line + 1) * lineHeight; justifyLine(positionedGlyphs, glyphs, lineStartIndex, positionedGlyphs.length - 1, justify); align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line); // Calculate the bounding box shaping.top += -verticalAlign * height; shaping.bottom = shaping.top + height; shaping.left += -horizontalAlign * maxLineLength; shaping.right = shaping.left + maxLineLength; } function justifyLine(positionedGlyphs, glyphs, start, end, justify) { var lastAdvance = glyphs[positionedGlyphs[end].codePoint].advance; var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify; for (var j = start; j <= end; j++) { positionedGlyphs[j].x -= lineIndent; } } function align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line) { var shiftX = (justify - horizontalAlign) * maxLineLength; var shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight; for (var j = 0; j < positionedGlyphs.length; j++) { positionedGlyphs[j].x += shiftX; positionedGlyphs[j].y += shiftY; } } function shapeIcon(image, layout) { if (!image || !image.rect) return null; var dx = layout['icon-offset'][0]; var dy = layout['icon-offset'][1]; var x1 = dx - image.width / 2; var x2 = x1 + image.width; var y1 = dy - image.height / 2; var y2 = y1 + image.height; return new PositionedIcon(image, y1, y2, x1, x2); } function PositionedIcon(image, top, bottom, left, right) { this.image = image; this.top = top; this.bottom = bottom; this.left = left; this.right = right; } },{}],73:[function(require,module,exports){ 'use strict'; var BinPack = require('./bin_pack'); module.exports = SpriteAtlas; function SpriteAtlas(width, height) { this.width = width; this.height = height; this.bin = new BinPack(width, height); this.images = {}; this.data = false; this.texture = 0; // WebGL ID this.filter = 0; // WebGL ID this.pixelRatio = 1; this.dirty = true; } SpriteAtlas.prototype = { get debug() { return 'canvas' in this; }, set debug(value) { if (value && !this.canvas) { this.canvas = document.createElement('canvas'); this.canvas.width = this.width * this.pixelRatio; this.canvas.height = this.height * this.pixelRatio; this.canvas.style.width = this.width + 'px'; this.canvas.style.width = this.width + 'px'; document.body.appendChild(this.canvas); this.ctx = this.canvas.getContext('2d'); } else if (!value && this.canvas) { this.canvas.parentNode.removeChild(this.canvas); delete this.ctx; delete this.canvas; } } }; SpriteAtlas.prototype.resize = function(newRatio) { if (this.pixelRatio === newRatio) return false; var oldRatio = this.pixelRatio; this.pixelRatio = newRatio; if (this.canvas) { this.canvas.width = this.width * this.pixelRatio; this.canvas.height = this.height * this.pixelRatio; } if (this.data) { var oldData = this.data; this.data = false; this.allocate(); this.texture = false; var oldWidth = this.width * oldRatio; var oldHeight = this.height * oldRatio; var newWidth = this.width * newRatio; var newHeight = this.height * newRatio; // Basic image scaling. TODO: Replace this with better image scaling. var newImage = this.data; var oldImage = oldData; for (var y = 0; y < newHeight; y++) { var oldYOffset = Math.floor((y * oldHeight) / newHeight) * oldWidth; var newYOffset = y * newWidth; for (var x = 0; x < newWidth; x++) { var oldX = Math.floor((x * oldWidth) / newWidth); newImage[newYOffset + x] = oldImage[oldYOffset + oldX]; } } oldData = null; this.dirty = true; } return this.dirty; }; function copyBitmap(src, srcStride, srcX, srcY, dst, dstStride, dstX, dstY, width, height, wrap) { var srcI = srcY * srcStride + srcX; var dstI = dstY * dstStride + dstX; var x, y; if (wrap) { // add 1 pixel wrapped padding on each side of the image dstI -= dstStride; for (y = -1; y <= height; y++, srcI = ((y + height) % height + srcY) * srcStride + srcX, dstI += dstStride) { for (x = -1; x <= width; x++) { dst[dstI + x] = src[srcI + ((x + width) % width)]; } } } else { for (y = 0; y < height; y++, srcI += srcStride, dstI += dstStride) { for (x = 0; x < width; x++) { dst[dstI + x] = src[srcI + x]; } } } } SpriteAtlas.prototype.allocateImage = function(pixelWidth, pixelHeight) { // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them // into 2 bytes rather than 4 bytes. // Pad icons to prevent them from polluting neighbours during linear interpolation var padding = 2; var packWidth = pixelWidth + padding + (4 - (pixelWidth + padding) % 4); var packHeight = pixelHeight + padding + (4 - (pixelHeight + padding) % 4);// + 4; // We have to allocate a new area in the bin, and store an empty image in it. // Add a 1px border around every image. var rect = this.bin.allocate(packWidth, packHeight); if (rect.w === 0) { return rect; } rect.originalWidth = pixelWidth; rect.originalHeight = pixelHeight; return rect; }; SpriteAtlas.prototype.getImage = function(name, wrap) { if (this.images[name]) { return this.images[name]; } if (!this.sprite) { return null; } var pos = this.sprite.getSpritePosition(name); if (!pos.width || !pos.height) { return null; } var width = pos.width / pos.pixelRatio; var height = pos.height / pos.pixelRatio; var rect = this.allocateImage(width, height); if (rect.w === 0) { return rect; } var image = new AtlasImage(rect, width, height, pos.sdf); this.images[name] = image; this.copy(rect, pos, wrap); return image; }; SpriteAtlas.prototype.getPosition = function(name, repeating) { var image = this.getImage(name, repeating); var rect = image && image.rect; if (!rect) { return null; } // When the image is repeating, get the correct position of the image, rather than the // one rounded up to 4 pixels. var width = repeating ? image.width : rect.w; var height = repeating ? image.height : rect.h; var padding = 1; return { size: [width, height], tl: [(rect.x + padding) / this.width, (rect.y + padding) / this.height], br: [(rect.x + padding + width) / this.width, (rect.y + padding + height) / this.height] }; }; SpriteAtlas.prototype.allocate = function() { if (!this.data) { var w = Math.floor(this.width * this.pixelRatio); var h = Math.floor(this.height * this.pixelRatio); this.data = new Uint32Array(w * h); for (var i = 0; i < this.data.length; i++) { this.data[i] = 0; } } }; SpriteAtlas.prototype.copy = function(dst, src, wrap) { // if (!sprite->raster) return; if (!this.sprite.img.data) return; var srcImg = new Uint32Array(this.sprite.img.data.buffer); this.allocate(); var dstImg = this.data; var padding = 1; copyBitmap( /* source buffer */ srcImg, /* source stride */ this.sprite.img.width, /* source x */ src.x, /* source y */ src.y, /* dest buffer */ dstImg, /* dest stride */ this.width * this.pixelRatio, /* dest x */ (dst.x + padding) * this.pixelRatio, /* dest y */ (dst.y + padding) * this.pixelRatio, /* icon dimension */ src.width, /* icon dimension */ src.height, /* wrap */ wrap ); this.dirty = true; }; SpriteAtlas.prototype.setSprite = function(sprite) { this.sprite = sprite; }; SpriteAtlas.prototype.addIcons = function(icons, callback) { for (var i = 0; i < icons.length; i++) { this.getImage(icons[i]); } callback(null, this.images); }; SpriteAtlas.prototype.bind = function(gl, linear) { var first = false; if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); first = true; } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } var filterVal = linear ? gl.LINEAR : gl.NEAREST; if (filterVal !== this.filter) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterVal); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterVal); this.filter = filterVal; } if (this.dirty) { this.allocate(); if (first) { gl.texImage2D( gl.TEXTURE_2D, // enum target 0, // ind level gl.RGBA, // ind internalformat this.width * this.pixelRatio, // GLsizei width this.height * this.pixelRatio, // GLsizei height 0, // ind border gl.RGBA, // enum format gl.UNSIGNED_BYTE, // enum type new Uint8Array(this.data.buffer) // Object data ); } else { gl.texSubImage2D( gl.TEXTURE_2D, // enum target 0, // int level 0, // int xoffset 0, // int yoffset this.width * this.pixelRatio, // long width this.height * this.pixelRatio, // long height gl.RGBA, // enum format gl.UNSIGNED_BYTE, // enum type new Uint8Array(this.data.buffer) // Object pixels ); } this.dirty = false; // DEBUG if (this.ctx) { var data = this.ctx.getImageData(0, 0, this.width * this.pixelRatio, this.height * this.pixelRatio); data.data.set(new Uint8ClampedArray(this.data.buffer)); this.ctx.putImageData(data, 0, 0); this.ctx.strokeStyle = 'red'; for (var k = 0; k < this.bin.free.length; k++) { var free = this.bin.free[k]; this.ctx.strokeRect(free.x * this.pixelRatio, free.y * this.pixelRatio, free.w * this.pixelRatio, free.h * this.pixelRatio); } } // END DEBUG } }; function AtlasImage(rect, width, height, sdf) { this.rect = rect; this.width = width; this.height = height; this.sdf = sdf; } },{"./bin_pack":59}],74:[function(require,module,exports){ 'use strict'; var util = require('../util/util'); var interpolate = require('../util/interpolate'); var browser = require('../util/browser'); var LatLng = require('../geo/lat_lng'); var LatLngBounds = require('../geo/lat_lng_bounds'); var Point = require('point-geometry'); /** * @typedef {Object} CameraOptions * @property {Array} [center] Latitude and longitude (passed as `[lat, lng]`) * @property {number} [zoom] Map zoom level * @property {number} [bearing] Map rotation bearing in degrees counter-clockwise from north * @property {number} [pitch] The angle at which the camera is looking at the ground */ /** * @typedef {Object} [AnimationOptions] * @property {number} [duration=500] Number in milliseconds * @property {Function} [easing] * @property {Array} [offset=[0,0]] point, origin of movement relative to map center * @property {boolean} [animate=true] When set to false, no animation happens */ var Camera = module.exports = function() {}; util.extend(Camera.prototype, /** @lends Map.prototype */{ /** * Get the current view geographical point. * @returns {LatLng} */ getCenter: function() { return this.transform.center; }, /** * Sets a map location. Equivalent to `jumpTo({center: center})`. * * @param {Array} center Latitude and longitude (passed as `[lat, lng]`) * @fires movestart * @fires moveend * @returns {Map} `this` * @example * map.setCenter([-74, 38]); */ setCenter: function(center) { this.jumpTo({center: center}); }, /** * Pan by a certain number of pixels * * @param {Array} offset [x, y] * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ panBy: function(offset, options) { this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options)); return this; }, /** * Pan to a certain location with easing * * @param {Object} latlng a `LatLng` object * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ panTo: function(latlng, options) { this.stop(); latlng = LatLng.convert(latlng); options = util.extend({ duration: 500, easing: util.ease, offset: [0, 0] }, options); var tr = this.transform, offset = Point.convert(options.offset).rotate(-tr.angle), from = tr.point, to = tr.project(latlng).sub(offset); if (!options.noMoveStart) { this.fire('movestart'); } this._ease(function(k) { tr.center = tr.unproject(from.add(to.sub(from).mult(k))); this.fire('move'); }, function() { this.fire('moveend'); }, options); return this; }, /** * Get the current zoom * @returns {number} */ getZoom: function() { return this.transform.zoom; }, /** * Sets a map zoom. Equivalent to `jumpTo({zoom: zoom})`. * * @param {number} zoom Map zoom level * @fires movestart * @fires moveend * @returns {Map} `this` * @example * // zoom the map to 5 * map.setZoom(5); */ setZoom: function(zoom) { this.jumpTo({zoom: zoom}); }, /** * Zooms to a certain zoom level with easing. * * @param {Number} zoom * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomTo: function(zoom, options) { this.stop(); options = util.extend({ duration: 500 }, options); options.easing = this._updateEasing(options.duration, zoom, options.easing); var tr = this.transform, around = tr.center, startZoom = tr.zoom; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } if (options.animate === false) options.duration = 0; if (!this.zooming) { this.zooming = true; this.fire('movestart'); } this._ease(function(k) { tr.setZoomAround(interpolate(startZoom, zoom, k), around); this.fire('move').fire('zoom'); }, function() { this.ease = null; if (options.duration >= 200) { this.zooming = false; this.fire('moveend'); } }, options); if (options.duration < 200) { clearTimeout(this._onZoomEnd); this._onZoomEnd = setTimeout(function() { this.zooming = false; this.fire('moveend'); }.bind(this), 200); } return this; }, /** * Zoom in by 1 level * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomIn: function(options) { this.zoomTo(this.getZoom() + 1, options); }, /** * Zoom out by 1 level * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ zoomOut: function(options) { this.zoomTo(this.getZoom() - 1, options); }, /** * Get the current bearing in degrees * @returns {number} */ getBearing: function() { return this.transform.bearing; }, /** * Sets a map rotation. Equivalent to `jumpTo({bearing: bearing})`. * * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north * @fires movestart * @fires moveend * @returns {Map} `this` * @example * // rotate the map to 90 degrees * map.setBearing(90); */ setBearing: function(bearing) { this.jumpTo({bearing: bearing}); }, /** * Rotate bearing by a certain number of degrees with easing * * @param {Number} bearing * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ rotateTo: function(bearing, options) { this.stop(); options = util.extend({ duration: 500, easing: util.ease }, options); var tr = this.transform, start = this.getBearing(), around = tr.center; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } bearing = this._normalizeBearing(bearing, start); this.rotating = true; this.fire('movestart'); this._ease(function(k) { tr.setBearingAround(interpolate(start, bearing, k), around); this.fire('move').fire('rotate'); }, function() { this.rotating = false; this.fire('moveend'); }, options); return this; }, /** * Sets map bearing to 0 (north) with easing * * @param {AnimationOptions} * @fires movestart * @fires moveend * @returns {this} */ resetNorth: function(options) { return this.rotateTo(0, util.extend({duration: 1000}, options)); }, /** * Get the current angle in degrees * @returns {number} */ getPitch: function() { return this.transform.pitch; }, /** * Sets a map angle. Equivalent to `jumpTo({pitch: pitch})`. * * @param {number} pitch The angle at which the camera is looking at the ground * @fires movestart * @fires moveend * @returns {Map} `this` */ setPitch: function(pitch) { this.jumpTo({pitch: pitch}); }, /** * Zoom to contain certain geographical bounds * * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]] * @param {Object} options * @param {Number} [options.speed=1.2] How fast animation occurs * @param {Number} [options.curve=1.42] How much zooming out occurs during animation * @param {Function} options.easing * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels * @param {Number} options.maxZoom * @fires movestart * @fires moveend * @returns {this} */ fitBounds: function(bounds, options) { options = util.extend({ padding: 0, offset: [0, 0], maxZoom: Infinity }, options); bounds = LatLngBounds.convert(bounds); var offset = Point.convert(options.offset), tr = this.transform, nw = tr.project(bounds.getNorthWest()), se = tr.project(bounds.getSouthEast()), size = se.sub(nw), scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x, scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y; options.center = tr.unproject(nw.add(se).div(2)); options.zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom); options.bearing = 0; return options.linear ? this.easeTo(options) : this.flyTo(options); }, /** * Change any combination of center, zoom, bearing, and pitch, without * a transition. The map will retain the current values for any options * not included in `options`. * * @param {CameraOptions} options map view options * @fires movestart * @fires moveend * @returns {Map} `this` */ jumpTo: function(options) { this.stop(); var tr = this.transform, zoomChanged = false, bearingChanged = false, pitchChanged = false; if ('center' in options) { tr.center = LatLng.convert(options.center); } if ('zoom' in options && tr.zoom !== +options.zoom) { zoomChanged = true; tr.zoom = +options.zoom; } if ('bearing' in options && tr.bearing !== +options.bearing) { bearingChanged = true; tr.bearing = +options.bearing; } if ('pitch' in options && tr.pitch !== +options.pitch) { pitchChanged = true; tr.pitch = +options.pitch; } this.fire('movestart') .fire('move'); if (zoomChanged) { this.fire('zoom'); } if (bearingChanged) { this.fire('rotate'); } if (pitchChanged) { this.fire('pitch'); } return this.fire('moveend'); }, /** * Easing animation to a specified location/zoom/bearing * * @param {CameraOptions+AnimationOptions} options map view and animation options * @fires movestart * @fires moveend * @returns {this} */ easeTo: function(options) { this.stop(); options = util.extend({ offset: [0, 0], duration: 500, easing: util.ease }, options); var tr = this.transform, offset = Point.convert(options.offset).rotate(-tr.angle), from = tr.point, startZoom = this.getZoom(), startBearing = this.getBearing(), startPitch = this.getPitch(); var zoom = 'zoom' in options ? +options.zoom : startZoom; var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing; var pitch = 'pitch' in options ? +options.pitch : startPitch; var scale = tr.zoomScale(zoom - startZoom), to = 'center' in options ? tr.project(LatLng.convert(options.center)).sub(offset.div(scale)) : from, around; if (zoom !== startZoom) { around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale))); this.zooming = true; } if (startBearing !== bearing) { this.rotating = true; } this.fire('movestart'); this._ease(function (k) { if (zoom !== startZoom) { tr.setZoomAround(interpolate(startZoom, zoom, k), around); } else { tr.center = tr.unproject(from.add(to.sub(from).mult(k))); } if (bearing !== startBearing) { tr.bearing = interpolate(startBearing, bearing, k); } if (pitch !== startPitch) { tr.pitch = interpolate(startPitch, pitch, k); } this.fire('move'); if (this.zooming) { this.fire('zoom'); } if (this.rotating) { this.fire('rotate'); } }, function() { this.zooming = false; this.rotating = false; this.fire('moveend'); }, options); return this; }, /** * Flying animation to a specified location/zoom/bearing with automatic curve * * @param {CameraOptions} options map view options * @param {Number} [options.speed=1.2] How fast animation occurs * @param {Number} [options.curve=1.42] How much zooming out occurs during animation * @param {Function} [options.easing] * @fires movestart * @fires moveend * @returns {this} * @example * // fly with default options to null island * map.flyTo({center: [0, 0], zoom: 9}); * // using flyTo options * map.flyTo({ * center: [0, 0], * zoom: 9, * speed: 0.2, * curve: 1, * easing: function(t) { * return t; * } * }); */ flyTo: function(options) { this.stop(); options = util.extend({ offset: [0, 0], speed: 1.2, curve: 1.42, easing: util.ease }, options); var tr = this.transform, offset = Point.convert(options.offset), startZoom = this.getZoom(), startBearing = this.getBearing(); var center = 'center' in options ? LatLng.convert(options.center) : this.getCenter(); var zoom = 'zoom' in options ? +options.zoom : startZoom; var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing; var scale = tr.zoomScale(zoom - startZoom), from = tr.point, to = tr.project(center).sub(offset.div(scale)); var startWorldSize = tr.worldSize, rho = options.curve, V = options.speed, w0 = Math.max(tr.width, tr.height), w1 = w0 / scale, u1 = to.sub(from).mag(), rho2 = rho * rho; function r(i) { var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1); return Math.log(Math.sqrt(b * b + 1) - b); } function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; } function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; } function tanh(n) { return sinh(n) / cosh(n); } var r0 = r(0), w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); }, u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; }, S = (r(1) - r0) / rho; if (Math.abs(u1) < 0.000001) { if (Math.abs(w0 - w1) < 0.000001) return this; var k = w1 < w0 ? -1 : 1; S = Math.abs(Math.log(w1 / w0)) / rho; u = function() { return 0; }; w = function(s) { return Math.exp(k * rho * s); }; } options.duration = 1000 * S / V; this.zooming = true; if (startBearing !== bearing) this.rotating = true; this.fire('movestart'); this._ease(function (k) { var s = k * S, us = u(s); tr.zoom = startZoom + tr.scaleZoom(1 / w(s)); tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize); if (bearing !== startBearing) { tr.bearing = interpolate(startBearing, bearing, k); } this.fire('move').fire('zoom'); if (bearing !== startBearing) { this.fire('rotate'); } }, function() { this.zooming = false; this.rotating = false; this.fire('moveend'); }, options); return this; }, isEasing: function() { return !!this._abortFn; }, /** * Stop current animation * * @returns {this} */ stop: function() { if (this._abortFn) { this._abortFn.call(this); delete this._abortFn; this._finishFn.call(this); delete this._finishFn; } return this; }, _ease: function(frame, finish, options) { this._finishFn = finish; this._abortFn = browser.timed(function (t) { frame.call(this, options.easing(t)); if (t === 1) { delete this._abortFn; this._finishFn.call(this); delete this._finishFn; } }, options.animate === false ? 0 : options.duration, this); }, // convert bearing so that it's numerically close to the current one so that it interpolates properly _normalizeBearing: function(bearing, currentBearing) { bearing = util.wrap(bearing, -180, 180); var diff = Math.abs(bearing - currentBearing); if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360; if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360; return bearing; }, _updateEasing: function(duration, zoom, bezier) { var easing; if (this.ease) { var ease = this.ease, t = (Date.now() - ease.start) / ease.duration, speed = ease.easing(t + 0.01) - ease.easing(t), // Quick hack to make new bezier that is continuous with last x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01, y = Math.sqrt(0.27 * 0.27 - x * x); easing = util.bezier(x, y, 0.25, 1); } else { easing = bezier ? util.bezier.apply(util, bezier) : util.ease; } // store information on current easing this.ease = { start: (new Date()).getTime(), to: Math.pow(2, zoom), duration: duration, easing: easing }; return easing; } }); },{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../util/browser":85,"../util/interpolate":92,"../util/util":96,"point-geometry":113}],75:[function(require,module,exports){ 'use strict'; var Control = require('./control'); var DOM = require('../../util/dom'); var util = require('../../util/util'); module.exports = Attribution; /** * Creates an attribution control * @class Attribution * @example * map.addControl(new mapboxgl.Attribution()); */ function Attribution() {} Attribution.prototype = util.inherit(Control, { options: { position: 'bottom-right' }, onAdd: function(map) { var className = 'mapboxgl-ctrl-attrib', container = this._container = DOM.create('div', className, map.getContainer()); this._update(); map.on('source.load', this._update.bind(this)); map.on('source.change', this._update.bind(this)); map.on('source.remove', this._update.bind(this)); map.on('moveend', this._updateEditLink.bind(this)); return container; }, _update: function() { var attributions = []; if (this._map.style) { for (var id in this._map.style.sources) { var source = this._map.style.sources[id]; if (source.attribution && attributions.indexOf(source.attribution) < 0) { attributions.push(source.attribution); } } } this._container.innerHTML = attributions.join(' | '); this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0]; this._updateEditLink(); }, _updateEditLink: function() { if (this._editLink) { var center = this._map.getCenter(); this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' + center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1); } } }); },{"../../util/dom":88,"../../util/util":96,"./control":76}],76:[function(require,module,exports){ 'use strict'; module.exports = Control; /** * A base class for map-related interface elements. * * @class Control */ function Control() {} Control.prototype = { /** * Add this control to the map, returning the control itself * for chaining. This will insert the control's DOM element into * the map's DOM element if the control has a `position` specified. * * @param {Map} map * @returns {Control} this */ addTo: function(map) { this._map = map; var container = this._container = this.onAdd(map); if (this.options && this.options.position) { var pos = this.options.position; var corner = map._controlCorners[pos]; container.className += ' mapboxgl-ctrl'; if (pos.indexOf('bottom') !== -1) { corner.insertBefore(container, corner.firstChild); } else { corner.appendChild(container); } } return this; }, /** * Remove this control from the map it has been added to. * * @returns {Control} this */ remove: function() { this._container.parentNode.removeChild(this._container); if (this.onRemove) this.onRemove(this._map); this._map = null; return this; } }; },{}],77:[function(require,module,exports){ 'use strict'; var Control = require('./control'); var DOM = require('../../util/dom'); var util = require('../../util/util'); module.exports = Navigation; /** * Creates a navigation control with zoom buttons and a compass * @class Navigation * @param {Object} [options] * @param {String} [options.position=top-right] A string indicating the control's position on the map. Options are `top-right`, `top-left`, `bottom-right`, `bottom-left` * @example * map.addControl(new mapboxgl.Navigation({position: 'top-left'})); // position is optional */ function Navigation(options) { util.setOptions(this, options); } Navigation.prototype = util.inherit(Control, { options: { position: 'top-right' }, onAdd: function(map) { var className = 'mapboxgl-ctrl'; var container = this._container = DOM.create('div', className + '-group', map.getContainer()); this._zoomInButton = this._createButton(className + '-icon ' + className + '-zoom-in', map.zoomIn.bind(map)); this._zoomOutButton = this._createButton(className + '-icon ' + className + '-zoom-out', map.zoomOut.bind(map)); this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map)); var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass); compassCanvas.style.cssText = 'width:30px; height:30px;'; compassCanvas.width = 26 * 2; compassCanvas.height = 26 * 2; this._compass.addEventListener('mousedown', this._onCompassDown.bind(this)); this._onCompassMove = this._onCompassMove.bind(this); this._onCompassUp = this._onCompassUp.bind(this); this._compassCtx = compassCanvas.getContext('2d'); map.on('rotate', this._drawNorth.bind(this)); this._drawNorth(); return container; }, _onCompassDown: function(e) { DOM.disableDrag(); document.addEventListener('mousemove', this._onCompassMove); document.addEventListener('mouseup', this._onCompassUp); this._prevX = e.screenX; e.stopPropagation(); }, _onCompassMove: function(e) { var x = e.screenX, d = x < 2 ? -5 : // left edge of the screen, continue rotating x > window.screen.width - 2 ? 5 : // right edge (x - this._prevX) / 4; this._map.setBearing(this._map.getBearing() - d); this._prevX = e.screenX; this._moved = true; e.preventDefault(); }, _onCompassUp: function() { document.removeEventListener('mousemove', this._onCompassMove); document.removeEventListener('mouseup', this._onCompassUp); DOM.enableDrag(); if (this._moved) { this._moved = false; DOM.suppressClick(); } }, _createButton: function(className, fn) { var a = DOM.create('button', className, this._container); a.addEventListener('click', function() { fn(); }); return a; }, _drawNorth: function() { var rad = 20, width = 8, center = 26, angle = this._map.transform.angle + (Math.PI / 2), ctx = this._compassCtx; this._compassCanvas.width = this._compassCanvas.width; ctx.translate(center, center); ctx.rotate(angle); ctx.beginPath(); ctx.fillStyle = '#000'; ctx.lineTo(0, -width); ctx.lineTo(-rad, 0); ctx.lineTo(0, width); ctx.fill(); ctx.beginPath(); ctx.fillStyle = '#bbb'; ctx.moveTo(0, 0); ctx.lineTo(0, width); ctx.lineTo(rad, 0); ctx.lineTo(0, -width); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = '#fff'; ctx.lineWidth = 4; ctx.moveTo(0, -width); ctx.lineTo(0, width); ctx.stroke(); } }); },{"../../util/dom":88,"../../util/util":96,"./control":76}],78:[function(require,module,exports){ 'use strict'; var Interaction = require('./interaction'); var Point = require('point-geometry'); var util = require('../util/util'); var DOM = require('../util/dom'); var LatLngBounds = require('../geo/lat_lng_bounds'); module.exports = Handlers; function Handlers(map) { var rotateEnd; var box; var inertiaLinearity = 0.2, inertiaEasing = util.bezier(0, 0, inertiaLinearity, 1); function boxzoomFinish() { if (box) { box.parentNode.removeChild(box); map.getContainer().classList.remove('mapboxgl-crosshair'); box = false; DOM.enableDrag(); } } this.interaction = new Interaction(map.getCanvas()) .on('click', function(e) { e.latLng = map.unproject(e.point); map.fire('click', e); }) .on('dblclick', function(e) { e.latLng = map.unproject(e.point); map.fire('dblclick', e); }) .on('mousemove', function(e) { e.latLng = map.unproject(e.point); map.fire('mousemove', e); }) .on('down', function() { map.fire('movestart'); }) .on('resize', function() { map.stop(); map.resize(); map.update(); }) .on('keydown', function(e) { if (e.altKey || e.ctrlKey || e.metaKey) return; var pan = 80; var rotate = 2; function zoomBy(z) { map.zoomTo(Math.round(map.getZoom()) + (e.shiftKey ? 2 : 1) * z); } function panBy(v) { map.panBy(v); } function rotateBy(v) { map.setBearing(map.getBearing() + v); } switch (e.keyCode) { case 61: case 107: case 171: case 187: zoomBy(1); break; case 189: case 109: case 173: zoomBy(-1); break; case 37: if (e.shiftKey) { rotateBy(-rotate); } else { panBy([-pan, 0]); } break; case 39: if (e.shiftKey) { rotateBy(rotate); } else { panBy([pan, 0]); } break; case 38: panBy([0, -pan]); break; case 40: panBy([0, pan]); break; default: return; } }) .on('pan', function(e) { map.stop(); var mouseLocation = map.transform.pointLocation(e.point.add(e.offset)); map.transform.setLocationAtPoint(mouseLocation, e.point); map.fire('move'); }) .on('panend', function(e) { if (!e.inertia) { map.fire('moveend'); } else { // convert velocity to px/s & adjust for increased initial animation speed when easing out var velocity = e.inertia.mult(1000 * inertiaLinearity), speed = velocity.mag(); var maxSpeed = 4000; // px/s if (speed >= maxSpeed) { speed = maxSpeed; velocity._unit()._mult(maxSpeed); } var deceleration = 8000, // px/s^2 duration = speed / (deceleration * inertiaLinearity), offset = velocity.mult(-duration / 2).round(); map.panBy(offset, { duration: duration * 1000, easing: inertiaEasing, noMoveStart: true }); } }) .on('zoom', function(e) { // Scale by sigmoid of scroll wheel delta. var scale = 2 / (1 + Math.exp(-Math.abs(e.delta / 100))); if (e.delta < 0 && scale !== 0) scale = 1 / scale; var fromScale = map.ease && isFinite(e.delta) ? map.ease.to : map.transform.scale, duration = !isFinite(e.delta) ? 800 : 0; map.zoomTo(map.transform.scaleZoom(fromScale * scale), { duration: duration, around: map.unproject(e.point) }); }) .on('rotate', function(e) { var center = map.transform.centerPoint, // Center of rotation startToCenter = e.start.sub(center), startToCenterDist = startToCenter.mag(); map.rotating = true; // If the first click was too close to the center, move the center of rotation by 200 pixels // in the direction of the click. if (startToCenterDist < 200) { center = e.start.add(new Point(-200, 0)._rotate(startToCenter.angle())); } var bearingDiff = e.prev.sub(center).angleWith(e.current.sub(center)) / Math.PI * 180; map.transform.bearing = map.getBearing() - bearingDiff; map.fire('move').fire('rotate'); window.clearTimeout(rotateEnd); rotateEnd = window.setTimeout(function() { map.rotating = false; map._rerender(); }, 200); }) .on('boxzoomstart', function(e) { if (!box) { box = DOM.create('div', 'mapboxgl-boxzoom', map.getContainer()); map.getContainer().classList.add('mapboxgl-crosshair'); map.fire('boxzoomstart'); DOM.disableDrag(); } var minX = Math.min(e.start.x, e.current.x); var maxX = Math.max(e.start.x, e.current.x); var minY = Math.min(e.start.y, e.current.y); var maxY = Math.max(e.start.y, e.current.y); DOM.setTransform(box, 'translate(' + minX + 'px,' + minY + 'px)'); box.style.width = (maxX - minX) + 'px'; box.style.height = (maxY - minY) + 'px'; }) .on('boxzoomend', function(e) { boxzoomFinish(); var bounds = new LatLngBounds( map.unproject(e.start), map.unproject(e.current) ); map.fitBounds(bounds, { linear: true }).fire('boxzoomend', { boxZoomBounds: bounds }); }) .on('boxzoomcancel', boxzoomFinish); } },{"../geo/lat_lng_bounds":19,"../util/dom":88,"../util/util":96,"./interaction":80,"point-geometry":113}],79:[function(require,module,exports){ 'use strict'; /* * Adds positional coordinates to URL hashes. Passed as an option to the map object * * @class mapboxgl.Hash * @returns {Hash} `this` */ module.exports = Hash; var util = require('../util/util'); function Hash() { util.bindAll([ '_onHashChange', '_updateHash' ], this); } Hash.prototype = { /* Map element to listen for coordinate changes * * @param {Object} map * @returns {Hash} `this` */ addTo: function(map) { this._map = map; window.addEventListener('hashchange', this._onHashChange, false); this._map.on('moveend', this._updateHash); return this; }, /* Removes hash * * @returns {Popup} `this` */ remove: function() { window.removeEventListener('hashchange', this._onHashChange, false); this._map.off('moveend', this._updateHash); delete this._map; return this; }, _onHashChange: function() { var loc = location.hash.replace('#', '').split('/'); if (loc.length >= 3) { this._map.jumpTo({ center: [+loc[1], +loc[2]], zoom: +loc[0], bearing: +(loc[3] || 0) }); return true; } return false; }, _updateHash: function() { var center = this._map.getCenter(), zoom = this._map.getZoom(), bearing = this._map.getBearing(), precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)), hash = '#' + (Math.round(zoom * 100) / 100) + '/' + center.lat.toFixed(precision) + '/' + center.lng.toFixed(precision) + (bearing ? '/' + (Math.round(bearing * 10) / 10) : ''); window.history.replaceState('', '', hash); } }; },{"../util/util":96}],80:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented'); var browser = require('../util/browser'); var Point = require('point-geometry'); module.exports = Interaction; /** * Mouse event * * @event Map#mousemove * @type {Object} * @property {Point} point the pixel location of the event * @property {Event} originalEvent the original DOM event */ /** * Double click event. * * @event Map#dblclick * @type {Object} * @property {Point} point the pixel location of the event */ /** * Pan event * * @event Map#pan * @type {Object} * @property {Point} point the pixel location of the event * @property {Point} offset a point representing the movement from the previous map location to the current one. */ /** * Pan end event * * @event Map#panend * @type {Object} * @property {number} velocity a measure of how much inertia was recorded in this pan motion */ function Interaction(el) { var interaction = this; if (!el) return; var rotating = false, panned = false, boxzoom = false, firstPos = null, pos = null, inertia = null, now; function mousePos(e) { var rect = el.getBoundingClientRect(); return new Point( e.clientX - rect.left - el.clientLeft, e.clientY - rect.top - el.clientTop); } el.addEventListener('contextmenu', function(ev) { rotating = true; firstPos = pos = mousePos(ev); ev.preventDefault(); }, false); el.addEventListener('mousedown', onmousedown, false); document.addEventListener('mouseup', onmouseup, false); document.addEventListener('mousemove', onmousemove, false); el.addEventListener('click', onclick, false); scrollwheel(zoom); el.addEventListener('dblclick', ondoubleclick, false); window.addEventListener('resize', resize, false); el.addEventListener('keydown', keydown, false); function zoom(type, delta, point) { interaction.fire('zoom', { source: type, delta: delta, point: point }); inertia = null; now = null; } function click(point, ev) { interaction.fire('click', {point: point, originalEvent: ev}); } function mousemove(point, ev) { interaction.fire('mousemove', {point: point, originalEvent: ev}); } function pan(point) { if (pos) { var offset = pos.sub(point); interaction.fire('pan', {offset: offset, point: point}); // add an averaged version of this movement to the inertia vector if (inertia) { var duration = Date.now() - now; // sometimes it's 0 after some erratic paning if (duration) { var time = duration + now; inertia.push([time, point]); while (inertia.length > 2 && time - inertia[0][0] > 100) inertia.shift(); } } else { inertia = []; } now = Date.now(); pos = point; } } function resize() { interaction.fire('resize'); } function keydown(ev) { if (boxzoom && ev.keyCode === 27) { interaction.fire('boxzoomcancel'); boxzoom = false; } interaction.fire('keydown', ev); } function rotate(point) { if (pos) { interaction.fire('rotate', { start: firstPos, prev: pos, current: point }); pos = point; } } function doubleclick(point, ev) { interaction.fire('dblclick', { point: point, originalEvent: ev }); } function onmousedown(ev) { firstPos = pos = mousePos(ev); interaction.fire('down'); if (ev.shiftKey || ((ev.which === 1) && (ev.button === 1))) { boxzoom = true; } } function onmouseup(ev) { panned = pos && firstPos && (pos.x !== firstPos.x || pos.y !== firstPos.y); rotating = false; pos = null; if (boxzoom) { interaction.fire('boxzoomend', { start: firstPos, current: mousePos(ev) }); boxzoom = false; } else if (inertia && inertia.length >= 2 && now > Date.now() - 100) { var last = inertia[inertia.length - 1], first = inertia[0], velocity = last[1].sub(first[1]).div(last[0] - first[0]); interaction.fire('panend', {inertia: velocity}); } else if (pos) { interaction.fire('panend'); } inertia = null; now = null; } function onmousemove(ev) { var point = mousePos(ev); if (boxzoom) { interaction.fire('boxzoomstart', { start: firstPos, current: point }); } else if (rotating) { rotate(point); } else if (pos) { pan(point); } else { var target = ev.toElement || ev.target; while (target && target !== el && target.parentNode) target = target.parentNode; if (target === el) { mousemove(point, ev); } } } function onclick(ev) { if (!panned) click(mousePos(ev), ev); } function ondoubleclick(ev) { doubleclick(mousePos(ev), ev); zoom('wheel', Infinity * (ev.shiftKey ? -1 : 1), mousePos(ev)); ev.preventDefault(); } function scrollwheel(callback) { var firefox = /Firefox/i.test(navigator.userAgent); var safari = /Safari/i.test(navigator.userAgent) && !/Chrom(ium|e)/i.test(navigator.userAgent); var time = window.performance || Date; el.addEventListener('wheel', wheel, false); el.addEventListener('mousewheel', mousewheel, false); var lastEvent = 0; var type = null; var typeTimeout = null; var initialValue = null; function scroll(value, ev) { var stamp = time.now(); var timeDelta = stamp - lastEvent; lastEvent = stamp; var point = mousePos(ev); if (value !== 0 && (value % 4.000244140625) === 0) { // This one is definitely a mouse wheel event. type = 'wheel'; // Normalize this value to match trackpad. value = Math.floor(value / 4); } else if (value !== 0 && Math.abs(value) < 4) { // This one is definitely a trackpad event because it is so small. type = 'trackpad'; } else if (timeDelta > 400) { // This is likely a new scroll action. type = null; initialValue = value; // Start a timeout in case this was a singular event, and dely it // by up to 40ms. typeTimeout = setTimeout(function() { type = 'wheel'; callback(type, -initialValue, point); }, 40); } else if (type === null) { // This is a repeating event, but we don't know the type of event // just yet. If the delta per time is small, we assume it's a // fast trackpad; otherwise we switch into wheel mode. type = (Math.abs(timeDelta * value) < 200) ? 'trackpad' : 'wheel'; // Make sure our delayed event isn't fired again, because we // accumulate the previous event (which was less than 40ms ago) into // this event. if (typeTimeout) { clearTimeout(typeTimeout); typeTimeout = null; value += initialValue; } } // Slow down zoom if shift key is held for more precise zooming if (ev.shiftKey && value) value = value / 4; // Only fire the callback if we actually know what type of scrolling // device the user uses. if (type !== null) { callback(type, -value, point); } } function wheel(e) { var deltaY = e.deltaY; // Firefox doubles the values on retina screens... if (firefox && e.deltaMode === window.WheelEvent.DOM_DELTA_PIXEL) deltaY /= browser.devicePixelRatio; if (e.deltaMode === window.WheelEvent.DOM_DELTA_LINE) deltaY *= 40; scroll(deltaY, e); e.preventDefault(); } function mousewheel(e) { var deltaY = -e.wheelDeltaY; if (safari) deltaY = deltaY / 3; scroll(deltaY, e); e.preventDefault(); } } } Interaction.prototype = Object.create(Evented); },{"../util/browser":85,"../util/evented":90,"point-geometry":113}],81:[function(require,module,exports){ 'use strict'; var Canvas = require('../util/canvas'); var util = require('../util/util'); var browser = require('../util/browser'); var Evented = require('../util/evented'); var DOM = require('../util/dom'); var Style = require('../style/style'); var AnimationLoop = require('../style/animation_loop'); var Painter = require('../render/painter'); var Transform = require('../geo/transform'); var Hash = require('./hash'); var Handlers = require('./handlers'); var Camera = require('./camera'); var LatLng = require('../geo/lat_lng'); var LatLngBounds = require('../geo/lat_lng_bounds'); var Point = require('point-geometry'); var Attribution = require('./control/attribution'); /** * Creates a map instance. * @class Map * @param {Object} options * @param {String} options.container HTML element to initialize the map in (or element id as string) * @param {Number} [options.minZoom=0] Minimum zoom of the map * @param {Number} [options.maxZoom=20] Maximum zoom of the map * @param {Object} options.style Map style and data source definition (either a JSON object or a JSON URL), described in the [style reference](https://mapbox.com/mapbox-gl-style-spec/) * @param {Boolean} [options.hash=false] If `true`, the map will track and update the page URL according to map position * @param {Boolean} [options.interactive=true] If `false`, no mouse, touch, or keyboard listeners are attached to the map, so it will not respond to input * @param {Array} options.classes Style class names with which to initialize the map * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected. * @param {Boolean} [options.preserveDrawingBuffer=false] If `true`, The maps canvas can be exported to a PNG using `map.getCanvas().toDataURL();`. This is false by default as a performance optimization. * @example * var map = new mapboxgl.Map({ * container: 'map', * center: [37.772537, -122.420679], * zoom: 13, * style: style_object, * hash: true * }); */ var Map = module.exports = function(options) { options = this.options = util.inherit(this.options, options); this.animationLoop = new AnimationLoop(); this.transform = new Transform(options.minZoom, options.maxZoom); if (options.maxBounds) { var b = LatLngBounds.convert(options.maxBounds); this.transform.latRange = [b.getSouth(), b.getNorth()]; this.transform.lngRange = [b.getWest(), b.getEast()]; } util.bindAll([ '_forwardStyleEvent', '_forwardSourceEvent', '_forwardLayerEvent', '_forwardTileEvent', '_onStyleLoad', '_onStyleChange', '_onSourceAdd', '_onSourceRemove', '_onSourceUpdate', 'update', 'render' ], this); this._setupContainer(); this._setupPainter(); this.on('move', this.update); this.on('zoom', this.update.bind(this, true)); this.on('moveend', function() { this.animationLoop.set(300); // text fading this._rerender(); }.bind(this)); this.handlers = options.interactive && new Handlers(this); this._hash = options.hash && (new Hash()).addTo(this); // don't set position from options if set through hash if (!this._hash || !this._hash._onHashChange()) { this.jumpTo(options); } this.sources = {}; this.stacks = {}; this._classes = {}; this.resize(); if (options.classes) this.setClasses(options.classes); if (options.style) this.setStyle(options.style); if (options.attributionControl) this.addControl(new Attribution()); }; util.extend(Map.prototype, Evented); util.extend(Map.prototype, Camera.prototype); util.extend(Map.prototype, /** @lends Map.prototype */{ options: { center: [0, 0], zoom: 0, bearing: 0, pitch: 0, minZoom: 0, maxZoom: 20, interactive: true, hash: false, attributionControl: true, failIfMajorPerformanceCaveat: false, preserveDrawingBuffer: false }, addControl: function(control) { control.addTo(this); return this; }, /** * @typedef {Object} [styleOptions] * @param {Boolean} [styleOptions.transition=true] */ /** * Adds a style class to a map * * @param {string} klass name of style class * @param {styleOptions} options * @fires change * @returns {Map} `this` */ addClass: function(klass, options) { if (this._classes[klass]) return; this._classes[klass] = true; if (this.style) this.style._cascade(this._classes, options); }, /** * Removes a style class from a map * * @param {string} klass name of style class * @param {styleOptions} options * @fires change * @returns {Map} `this` */ removeClass: function(klass, options) { if (!this._classes[klass]) return; delete this._classes[klass]; if (this.style) this.style._cascade(this._classes, options); }, /** * Helper method to add more than one class * * @param {Array<string>} klasses An array of class names * @param {styleOptions} options * @fires change * @returns {Map} `this` */ setClasses: function(klasses, options) { this._classes = {}; for (var i = 0; i < klasses.length; i++) { this._classes[klasses[i]] = true; } if (this.style) this.style._cascade(this._classes, options); }, /** * Check whether a style class is active * * @param {string} klass Name of style class * @returns {boolean} */ hasClass: function(klass) { return !!this._classes[klass]; }, /** * Return an array of the current active style classes * * @returns {boolean} */ getClasses: function() { return Object.keys(this._classes); }, /** * Detect the map's new width and height and resize it. * * @returns {Map} `this` */ resize: function() { var width = 0, height = 0; if (this._container) { width = this._container.offsetWidth || 400; height = this._container.offsetHeight || 300; } this._canvas.resize(width, height); this.transform.width = width; this.transform.height = height; this.transform._constrain(); this.painter.resize(width, height); return this .fire('movestart') .fire('move') .fire('resize') .fire('moveend'); }, /** * Get the map's geographical bounds * * @returns {LatLngBounds} */ getBounds: function() { return new LatLngBounds( this.transform.pointLocation(new Point(0, 0)), this.transform.pointLocation(this.transform.size)); }, /** * Get pixel coordinates (relative to map container) given a geographical location * * @param {LatLng} latlng * @returns {Object} `x` and `y` coordinates */ project: function(latlng) { return this.transform.locationPoint(LatLng.convert(latlng)); }, /** * Get geographical coordinates given pixel coordinates * * @param {Array<number>} point [x, y] pixel coordinates * @returns {LatLng} */ unproject: function(point) { return this.transform.pointLocation(Point.convert(point)); }, /** * Get all features at a point ([x, y]) * * @param {Array<number>} point [x, y] pixel coordinates * @param {Object} params * @param {number} [params.radius=0] Optional. Radius in pixels to search in * @param {string} params.layer Optional. Only return features from a given layer * @param {string} params.type Optional. Either `raster` or `vector` * @param {featuresAtCallback} callback function that returns the response * * @callback featuresAtCallback * @param {Object|null} err Error _If any_ * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt` * * @returns {Map} `this` * * @example * map.featuresAt([10, 20], { radius: 10 }, function(err, features) { * console.log(features); * }); */ featuresAt: function(point, params, callback) { var coord = this.transform.pointCoordinate(Point.convert(point)); this.style.featuresAt(coord, params, callback); return this; }, /** * Replaces the map's style object * * @param {Object} style A style object formatted as JSON * @returns {Map} `this` */ setStyle: function(style) { if (this.style) { this.style .off('load', this._onStyleLoad) .off('error', this._forwardStyleEvent) .off('change', this._onStyleChange) .off('source.add', this._onSourceAdd) .off('source.remove', this._onSourceRemove) .off('source.load', this._onSourceUpdate) .off('source.error', this._forwardSourceEvent) .off('source.change', this._onSourceUpdate) .off('layer.add', this._forwardLayerEvent) .off('layer.remove', this._forwardLayerEvent) .off('tile.add', this._forwardTileEvent) .off('tile.remove', this._forwardTileEvent) .off('tile.load', this.update) .off('tile.error', this._forwardTileEvent) ._remove(); this.off('rotate', this.style._redoPlacement); this.off('pitch', this.style._redoPlacement); } if (!style) { this.style = null; return this; } else if (style instanceof Style) { this.style = style; } else { this.style = new Style(style, this.animationLoop); } this.style .on('load', this._onStyleLoad) .on('error', this._forwardStyleEvent) .on('change', this._onStyleChange) .on('source.add', this._onSourceAdd) .on('source.remove', this._onSourceRemove) .on('source.load', this._onSourceUpdate) .on('source.error', this._forwardSourceEvent) .on('source.change', this._onSourceUpdate) .on('layer.add', this._forwardLayerEvent) .on('layer.remove', this._forwardLayerEvent) .on('tile.add', this._forwardTileEvent) .on('tile.remove', this._forwardTileEvent) .on('tile.load', this.update) .on('tile.error', this._forwardTileEvent); this.on('rotate', this.style._redoPlacement); this.on('pitch', this.style._redoPlacement); return this; }, /** * Add a source to the map style. * * @param {string} id ID of the source. Must not be used by any existing source. * @param {Object} source source specification, following the * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources) * @fires source.add * @returns {Map} `this` */ addSource: function(id, source) { this.style.addSource(id, source); return this; }, /** * Remove an existing source from the map style. * * @param {string} id ID of the source to remove * @fires source.remove * @returns {Map} `this` */ removeSource: function(id) { this.style.removeSource(id); return this; }, /** * Return the style source object with the given `id`. * * @param {string} id source ID * @returns {Object} */ getSource: function(id) { return this.style.getSource(id); }, /** * Add a layer to the map style. The layer will be inserted before the layer with * ID `before`, or appended if `before` is omitted. * @param {StyleLayer|Object} layer * @param {string=} before ID of an existing layer to insert before * @fires layer.add * @returns {Map} `this` */ addLayer: function(layer, before) { this.style.addLayer(layer, before); this.style._cascade(this._classes); return this; }, /** * Remove the layer with the given `id` from the map. Any layers which refer to the * specified layer via a `ref` property are also removed. * * @param {string} id layer id * @fires layer.remove * @returns {Map} this */ removeLayer: function(id) { this.style.removeLayer(id); this.style._cascade(this._classes); return this; }, /** * Set the filter for a given style layer. * * @param {string} layer ID of a layer * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter) * @returns {Map} `this` */ setFilter: function(layer, filter) { this.style.setFilter(layer, filter); return this; }, /** * Get the filter for a given style layer. * * @param {string} layer ID of a layer * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter) */ getFilter: function(layer) { return this.style.getFilter(layer); }, /** * Set the value of a paint property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a paint property * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * @param {string=} klass optional class specifier for the property * @returns {Map} `this` */ setPaintProperty: function(layer, name, value, klass) { this.style.setPaintProperty(layer, name, value, klass); this.style._cascade(this._classes); this.update(true); return this; }, /** * Get the value of a paint property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a paint property * @param {string=} klass optional class specifier for the property * @returns {*} value for the paint propery */ getPaintProperty: function(layer, name, klass) { return this.style.getPaintProperty(layer, name, klass); }, /** * Set the value of a layout property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a layout property * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * @returns {Map} `this` */ setLayoutProperty: function(layer, name, value) { this.style.setLayoutProperty(layer, name, value); return this; }, /** * Get the value of a layout property in a given style layer. * * @param {string} layer ID of a layer * @param {string} name name of a layout property * @param {string=} klass optional class specifier for the property * @returns {*} value for the layout propery */ getLayoutProperty: function(layer, name) { return this.style.getLayoutProperty(layer, name); }, /** * Get the Map's container as an HTML element * @returns {HTMLElement} container */ getContainer: function() { return this._container; }, /** * Get the container for the map `canvas` element. * * If you want to add non-GL overlays to the map, you should append them to this element. This * is the element to which event bindings for map interactivity such as panning and zooming are * attached. It will receive bubbled events for child elements such as the `canvas`, but not for * map controls. * * @returns {HTMLElement} container */ getCanvasContainer: function() { return this._canvasContainer; }, /** * Get the Map's canvas as an HTML canvas * @returns {HTMLElement} canvas */ getCanvas: function() { return this._canvas.getElement(); }, _setupContainer: function() { var id = this.options.container; var container = this._container = typeof id === 'string' ? document.getElementById(id) : id; container.classList.add('mapboxgl-map'); var canvasContainer = this._canvasContainer = DOM.create('div', 'mapboxgl-canvas-container', container); if (this.options.interactive) { canvasContainer.classList.add('mapboxgl-interactive'); } this._canvas = new Canvas(this, canvasContainer); var controlContainer = DOM.create('div', 'mapboxgl-control-container', container); var corners = this._controlCorners = {}; ['top-left', 'top-right', 'bottom-left', 'bottom-right'].forEach(function (pos) { corners[pos] = DOM.create('div', 'mapboxgl-ctrl-' + pos, controlContainer); }); }, _setupPainter: function() { var gl = this._canvas.getWebGLContext({ failIfMajorPerformanceCaveat: this.options.failIfMajorPerformanceCaveat, preserveDrawingBuffer: this.options.preserveDrawingBuffer }); if (!gl) { console.error('Failed to initialize WebGL'); return; } this.painter = new Painter(gl, this.transform); }, _contextLost: function(event) { event.preventDefault(); if (this._frameId) { browser.cancelFrame(this._frameId); } }, _contextRestored: function() { this._setupPainter(); this.resize(); this.update(); }, /** * Is this map fully loaded? If the style isn't loaded * or it has a change to the sources or style that isn't * propagated to its style, return false. * * @returns {boolean} whether the map is loaded */ loaded: function() { if (this._styleDirty || this._sourcesDirty) return false; if (this.style && !this.style.loaded()) return false; return true; }, /** * Update this map's style and re-render the map. * * @param {Object} updateStyle new style * @returns {Map} this */ update: function(updateStyle) { if (!this.style) return this; this._styleDirty = this._styleDirty || updateStyle; this._sourcesDirty = true; this._rerender(); return this; }, /** * Call when a (re-)render of the map is required, e.g. when the * user panned or zoomed,f or new data is available. * @returns {Map} this */ render: function() { if (this.style && this._styleDirty) { this._styleDirty = false; this.style._recalculate(this.transform.zoom); } if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) { this._sourcesDirty = false; this._sourcesDirtyTimeout = setTimeout(function() { this._sourcesDirtyTimeout = null; }.bind(this), 50); this.style._updateSources(this.transform); } this.painter.render(this.style, { debug: this.debug, vertices: this.vertices, rotating: this.rotating, zooming: this.zooming }); this.fire('render'); if (this.loaded() && !this._loaded) { this._loaded = true; this.fire('load'); } this._frameId = null; if (!this.animationLoop.stopped()) { this._styleDirty = true; } if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) { this._rerender(); } return this; }, /** * Destroys the map's underlying resources, including web workers. * @returns {Map} this */ remove: function() { if (this._hash) this._hash.remove(); browser.cancelFrame(this._frameId); clearTimeout(this._sourcesDirtyTimeout); this.setStyle(null); return this; }, _rerender: function() { if (this.style && !this._frameId) { this._frameId = browser.frame(this.render); } }, _forwardStyleEvent: function(e) { this.fire('style.' + e.type, util.extend({style: e.target}, e)); }, _forwardSourceEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _forwardLayerEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _forwardTileEvent: function(e) { this.fire(e.type, util.extend({style: e.target}, e)); }, _onStyleLoad: function(e) { this.style._cascade(this._classes, {transition: false}); this._forwardStyleEvent(e); }, _onStyleChange: function(e) { this.update(true); this._forwardStyleEvent(e); }, _onSourceAdd: function(e) { var source = e.source; if (source.onAdd) source.onAdd(this); this._forwardSourceEvent(e); }, _onSourceRemove: function(e) { var source = e.source; if (source.onRemove) source.onRemove(this); this._forwardSourceEvent(e); }, _onSourceUpdate: function(e) { this.update(); this._forwardSourceEvent(e); } }); util.extendAll(Map.prototype, { /** * Enable debugging mode * * @name debug * @memberof Map * @type {boolean} */ _debug: false, get debug() { return this._debug; }, set debug(value) { this._debug = value; this.update(); }, /** * Show collision boxes: useful for debugging label placement * in styles. * * @name collisionDebug * @memberof Map * @type {boolean} */ _collisionDebug: false, get collisionDebug() { return this._collisionDebug; }, set collisionDebug(value) { this._collisionDebug = value; for (var i in this.style.sources) { if (this.style.sources[i].reload) { this.style.sources[i].reload(); } } this.update(); }, /** * Enable continuous repaint to analyze performance * * @name repaint * @memberof Map * @type {boolean} */ _repaint: false, get repaint() { return this._repaint; }, set repaint(value) { this._repaint = value; this.update(); }, // show vertices _vertices: false, get vertices() { return this._vertices; }, set vertices(value) { this._vertices = value; this.update(); } }); },{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../geo/transform":20,"../render/painter":34,"../style/animation_loop":47,"../style/style":52,"../util/browser":85,"../util/canvas":86,"../util/dom":88,"../util/evented":90,"../util/util":96,"./camera":74,"./control/attribution":75,"./handlers":78,"./hash":79,"point-geometry":113}],82:[function(require,module,exports){ 'use strict'; module.exports = Popup; var util = require('../util/util'); var Evented = require('../util/evented'); var DOM = require('../util/dom'); var LatLng = require('../geo/lat_lng'); /** * Creates a popup component * @class Popup * @param {Object} options * @param {Boolean} options.closeButton * @param {Boolean} options.closeOnClick * @example * var tooltip = new mapboxgl.Popup() * .setLatLng(map.unproject(e.point)) * .setHTML("<h1>Hello World!</h1>") * .addTo(map); */ function Popup(options) { util.setOptions(this, options); util.bindAll([ '_updatePosition', '_onClickClose'], this); } Popup.prototype = util.inherit(Evented, /** @lends Popup.prototype */{ options: { closeButton: true, closeOnClick: true }, /** * Attaches the popup to a map * @param {Map} map * @returns {Popup} `this` */ addTo: function(map) { this._map = map; this._map.on('move', this._updatePosition); if (this.options.closeOnClick) { this._map.on('click', this._onClickClose); } this._update(); return this; }, /** * Removes the popup from the map * @example * var popup = new mapboxgl.Popup().addTo(map); * popup.remove(); * @returns {Popup} `this` */ remove: function() { if (this._container) { this._container.parentNode.removeChild(this._container); } if (this._map) { this._map.off('move', this._updatePosition); this._map.off('click', this._onClickClose); delete this._map; } return this; }, /** * Get the current coordinates of popup element relative to map * @returns {LatLng} */ getLatLng: function() { return this._latLng; }, /** * Set the coordinates of a popup element to a map * @param {LatLng} latlng * @returns {Popup} `this` */ setLatLng: function(latlng) { this._latLng = LatLng.convert(latlng); this._update(); return this; }, /** * Fill a popup element with text only content * @param {string} text * @returns {Popup} `this` */ setText: function(text) { this._content = document.createTextNode(text); this._updateContent(); return this; }, /** * Fill a popup element with HTML content * @param {string} html * @returns {Popup} `this` */ setHTML: function(html) { this._content = document.createDocumentFragment(); var temp = document.createElement('body'), child; temp.innerHTML = html; while (true) { child = temp.firstChild; if (!child) break; this._content.appendChild(child); } this._updateContent(); return this; }, _update: function() { if (!this._map) { return; } if (!this._container) { this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer()); this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container); this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container); if (this.options.closeButton) { this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper); this._closeButton.innerHTML = '&#215;'; this._closeButton.addEventListener('click', this._onClickClose); } } this._updateContent(); this._updatePosition(); }, _updateContent: function() { if (!this._content || !this._container) { return; } var node = this._wrapper; while (node.hasChildNodes()) { node.removeChild(node.firstChild); } node.appendChild(this._closeButton); node.appendChild(this._content); }, _updatePosition: function() { if (!this._latLng || !this._container) { return; } var pos = this._map.project(this._latLng).round(), anchor = this.options.anchor; if (!anchor) { var width = this._container.offsetWidth, height = this._container.offsetHeight; if (pos.y < height) { anchor = ['top']; } else if (pos.y > this._map.transform.height - height) { anchor = ['bottom']; } else { anchor = []; } if (pos.x < width / 2) { anchor.push('left'); } else if (pos.x > this._map.transform.width - width / 2) { anchor.push('right'); } if (anchor.length === 0) { anchor = 'bottom'; } else { anchor = anchor.join('-'); } this.options.anchor = anchor; } var anchorTranslate = { 'top': 'translate(-50%,0)', 'top-left': 'translate(0,0)', 'top-right': 'translate(-100%,0)', 'bottom': 'translate(-50%,-100%)', 'bottom-left': 'translate(0,-100%)', 'bottom-right': 'translate(-100%,-100%)', 'left': 'translate(0,-50%)', 'right': 'translate(-100%,-50%)' }; var classList = this._container.classList; for (var key in anchorTranslate) { classList.remove('mapboxgl-popup-anchor-' + key); } classList.add('mapboxgl-popup-anchor-' + anchor); DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)'); }, _onClickClose: function() { this.remove(); } }); },{"../geo/lat_lng":18,"../util/dom":88,"../util/evented":90,"../util/util":96}],83:[function(require,module,exports){ 'use strict'; module.exports = Actor; /** * An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model) * that maintains the relationship between asynchronous tasks and the objects * that spin them off - in this case, tasks like parsing parts of styles, * owned by the styles * * @param {WebWorker} target * @param {WebWorker} parent * @private */ function Actor(target, parent) { this.target = target; this.parent = parent; this.callbacks = {}; this.callbackID = 0; this.receive = this.receive.bind(this); this.target.addEventListener('message', this.receive, false); } Actor.prototype.receive = function(message) { var data = message.data, callback; if (data.type === '<response>') { callback = this.callbacks[data.id]; delete this.callbacks[data.id]; callback(data.error || null, data.data); } else if (typeof data.id !== 'undefined') { var id = data.id; this.parent[data.type](data.data, function(err, data, buffers) { this.postMessage({ type: '<response>', id: String(id), error: err ? String(err) : null, data: data }, buffers); }.bind(this)); } else { this.parent[data.type](data.data); } }; Actor.prototype.send = function(type, data, callback, buffers) { var id = null; if (callback) this.callbacks[id = this.callbackID++] = callback; this.postMessage({ type: type, id: String(id), data: data }, buffers); }; /** * Wrapped postMessage API that abstracts around IE's lack of * `transferList` support. * * @param {Object} message * @param {Object} transferList */ Actor.prototype.postMessage = function(message, transferList) { try { this.target.postMessage(message, transferList); } catch (e) { this.target.postMessage(message); // No support for transferList on IE } }; },{}],84:[function(require,module,exports){ 'use strict'; exports.getJSON = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { var data; try { data = JSON.parse(xhr.response); } catch (err) { return callback(err); } callback(null, data); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getArrayBuffer = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { callback(null, xhr.response); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getImage = function(url, callback) { var img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = function() { callback(null, img); }; img.src = url; img.getData = function() { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); return context.getImageData(0, 0, img.width, img.height).data; }; return img; }; exports.getVideo = function(urls, callback) { var video = document.createElement('video'); video.crossOrigin = 'Anonymous'; video.onloadstart = function() { callback(null, video); }; for (var i = 0; i < urls.length; i++) { var s = document.createElement('source'); s.src = urls[i]; video.appendChild(s); } video.getData = function() { return video; }; return video; }; },{}],85:[function(require,module,exports){ 'use strict'; var Canvas = require('./canvas'); var frame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; exports.frame = function(fn) { return frame(fn); }; var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; exports.cancelFrame = function(id) { cancel(id); }; exports.timed = function (fn, dur, ctx) { if (!dur) { fn.call(ctx, 1); return null; } var abort = false, start = window.performance ? window.performance.now() : Date.now(); function tick(now) { if (abort) return; if (!window.performance) now = Date.now(); if (now >= start + dur) { fn.call(ctx, 1); } else { fn.call(ctx, (now - start) / dur); exports.frame(tick); } } exports.frame(tick); return function() { abort = true; }; }; /** * Test whether the basic JavaScript and DOM features required for Mapbox GL are present. * @param {Object} options * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected. * @return {Boolean} Returns true if Mapbox GL should be expected to work, and false if not. */ exports.supported = function(options) { var supports = [ function() { return typeof window !== 'undefined'; }, function() { return typeof document !== 'undefined'; }, function () { return !!(Array.prototype && Array.prototype.every && Array.prototype.filter && Array.prototype.forEach && Array.prototype.indexOf && Array.prototype.lastIndexOf && Array.prototype.map && Array.prototype.some && Array.prototype.reduce && Array.prototype.reduceRight && Array.isArray); }, function() { return !!(Function.prototype && Function.prototype.bind) && !!(Object.keys && Object.create && Object.getPrototypeOf && Object.getOwnPropertyNames && Object.isSealed && Object.isFrozen && Object.isExtensible && Object.getOwnPropertyDescriptor && Object.defineProperty && Object.defineProperties && Object.seal && Object.freeze && Object.preventExtensions); }, function() { return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON; }, function() { return new Canvas().supportsWebGLContext((options && options.failIfMajorPerformanceCaveat) || false); }, function() { return 'Worker' in window; } ]; for (var i = 0; i < supports.length; i++) { if (!supports[i]()) return false; } return true; }; exports.hardwareConcurrency = navigator.hardwareConcurrency || 8; Object.defineProperty(exports, 'devicePixelRatio', { get: function() { return window.devicePixelRatio; } }); },{"./canvas":86}],86:[function(require,module,exports){ 'use strict'; var util = require('../util'); module.exports = Canvas; function Canvas(parent, container) { this.canvas = document.createElement('canvas'); if (parent && container) { this.canvas.style.position = 'absolute'; this.canvas.classList.add('mapboxgl-canvas'); this.canvas.addEventListener('webglcontextlost', parent._contextLost.bind(parent), false); this.canvas.addEventListener('webglcontextrestored', parent._contextRestored.bind(parent), false); this.canvas.setAttribute('tabindex', 0); container.appendChild(this.canvas); } } Canvas.prototype.resize = function(width, height) { var pixelRatio = window.devicePixelRatio || 1; // Request the required canvas size taking the pixelratio into account. this.canvas.width = pixelRatio * width; this.canvas.height = pixelRatio * height; // Maintain the same canvas size, potentially downscaling it for HiDPI displays this.canvas.style.width = width + 'px'; this.canvas.style.height = height + 'px'; }; var requiredContextAttributes = { antialias: false, alpha: true, stencil: true, depth: false }; Canvas.prototype.getWebGLContext = function(attributes) { attributes = util.extend({}, attributes, requiredContextAttributes); return this.canvas.getContext('webgl', attributes) || this.canvas.getContext('experimental-webgl', attributes); }; Canvas.prototype.supportsWebGLContext = function(failIfMajorPerformanceCaveat) { var attributes = util.extend({ failIfMajorPerformanceCaveat: failIfMajorPerformanceCaveat }, requiredContextAttributes); if ('probablySupportsContext' in this.canvas) { return this.canvas.probablySupportsContext('webgl', attributes) || this.canvas.probablySupportsContext('experimental-webgl', attributes); } else if ('supportsContext' in this.canvas) { return this.canvas.supportsContext('webgl', attributes) || this.canvas.supportsContext('experimental-webgl', attributes); } return !!window.WebGLRenderingContext && !!this.getWebGLContext(failIfMajorPerformanceCaveat); }; Canvas.prototype.getElement = function() { return this.canvas; }; },{"../util":96}],87:[function(require,module,exports){ 'use strict'; var Actor = require('../actor'); var WebWorkify = require('webworkify'); module.exports = Dispatcher; function Dispatcher(length, parent) { this.actors = []; this.currentActor = 0; for (var i = 0; i < length; i++) { var worker = new WebWorkify(require('../../source/worker')); var actor = new Actor(worker, parent); actor.name = "Worker " + i; this.actors.push(actor); } } Dispatcher.prototype = { broadcast: function(type, data) { for (var i = 0; i < this.actors.length; i++) { this.actors[i].send(type, data); } }, send: function(type, data, callback, targetID, buffers) { if (typeof targetID !== 'number' || isNaN(targetID)) { // Use round robin to send requests to web workers. targetID = this.currentActor = (this.currentActor + 1) % this.actors.length; } this.actors[targetID].send(type, data, callback, buffers); return targetID; }, remove: function() { for (var i = 0; i < this.actors.length; i++) { this.actors[i].target.terminate(); } this.actors = []; } }; },{"../../source/worker":45,"../actor":83,"webworkify":125}],88:[function(require,module,exports){ 'use strict'; exports.create = function (tagName, className, container) { var el = document.createElement(tagName); if (className) el.className = className; if (container) container.appendChild(el); return el; }; var docStyle = document.documentElement.style; function testProp(props) { for (var i = 0; i < props.length; i++) { if (props[i] in docStyle) { return props[i]; } } } var selectProp = testProp(['userSelect', 'MozUserSelect', 'WebkitUserSelect', 'msUserSelect']), userSelect; exports.disableDrag = function () { if (selectProp) { userSelect = docStyle[selectProp]; docStyle[selectProp] = 'none'; } }; exports.enableDrag = function () { if (selectProp) { docStyle[selectProp] = userSelect; } }; var transformProp = testProp(['transform', 'WebkitTransform']); exports.setTransform = function(el, value) { el.style[transformProp] = value; }; // Suppress the next click, but only if it's immediate. function suppressClick(e) { e.preventDefault(); e.stopPropagation(); window.removeEventListener('click', suppressClick, true); } exports.suppressClick = function() { window.addEventListener('click', suppressClick, true); window.setTimeout(function() { window.removeEventListener('click', suppressClick, true); }, 0); }; },{}],89:[function(require,module,exports){ 'use strict'; module.exports = { HTTP_URL: 'http://a.tiles.mapbox.com', HTTPS_URL: 'https://a.tiles.mapbox.com', FORCE_HTTPS: true, REQUIRE_ACCESS_TOKEN: true }; },{}],90:[function(require,module,exports){ 'use strict'; var util = require('./util'); /** * Methods mixed in to other classes for event capabilities. * @mixin Evented */ var Evented = { /** * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties * * @param {String} type Event type * @param {Function} listener Function to be called when the event is fired */ on: function(type, fn) { this._events = this._events || {}; this._events[type] = this._events[type] || []; this._events[type].push(fn); return this; }, /** * Remove a event listener * * @param {String} [type] Event type. If none is specified, remove all listeners * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed */ off: function(type, fn) { if (!type) { // clear all listeners if no arguments specified delete this._events; return this; } if (!this.listens(type)) return this; if (fn) { var idx = this._events[type].indexOf(fn); if (idx >= 0) { this._events[type].splice(idx, 1); } if (!this._events[type].length) { delete this._events[type]; } } else { delete this._events[type]; } return this; }, /** * Call a function once when an event has fired * * @param {String} type Event type. * @param {Function} listener Function to be called once when the event is fired */ once: function(type, fn) { var wrapper = function(data) { this.off(type, wrapper); fn.call(this, data); }.bind(this); this.on(type, wrapper); return this; }, /** * Fire event of a given string type with the given data object * * @param {String} type The event name * @param {Object} [data] Optional data passed down to the event object * @returns {Boolean} Returns true if the object listens to an event of a particular type */ fire: function(type, data) { if (!this.listens(type)) return this; data = util.extend({}, data); util.extend(data, {type: type, target: this}); // make sure adding/removing listeners inside other listeners won't cause infinite loop var listeners = this._events[type].slice(); for (var i = 0; i < listeners.length; i++) { listeners[i].call(this, data); } return this; }, /** * Check if an event is registered to a type * @returns {Boolean} Returns true if the object listens to an event of a particular type */ listens: function(type) { return !!(this._events && this._events[type]); } }; module.exports = Evented; },{"./util":96}],91:[function(require,module,exports){ 'use strict'; module.exports = Glyphs; function Glyphs(pbf, end) { this.stacks = pbf.readFields(readFontstacks, [], end); } function readFontstacks(tag, stacks, pbf) { if (tag === 1) { var fontstack = pbf.readMessage(readFontstack, {glyphs: {}}); stacks.push(fontstack); } } function readFontstack(tag, fontstack, pbf) { if (tag === 1) fontstack.name = pbf.readString(); else if (tag === 2) fontstack.range = pbf.readString(); else if (tag === 3) { var glyph = pbf.readMessage(readGlyph, {}); fontstack.glyphs[glyph.id] = glyph; } } function readGlyph(tag, glyph, pbf) { if (tag === 1) glyph.id = pbf.readVarint(); else if (tag === 2) glyph.bitmap = pbf.readBytes(); else if (tag === 3) glyph.width = pbf.readVarint(); else if (tag === 4) glyph.height = pbf.readVarint(); else if (tag === 5) glyph.left = pbf.readSVarint(); else if (tag === 6) glyph.top = pbf.readSVarint(); else if (tag === 7) glyph.advance = pbf.readVarint(); } },{}],92:[function(require,module,exports){ 'use strict'; module.exports = interpolate; function interpolate(a, b, t) { return (a * (1 - t)) + (b * t); } interpolate.number = interpolate; interpolate.vec2 = function(from, to, t) { return [ interpolate(from[0], to[0], t), interpolate(from[1], to[1], t) ]; }; /* * Interpolate between two colors given as 4-element arrays. * * @param {Color} from * @param {Color} to * @param {Number} t interpolation factor between 0 and 1 * @returns {Color} interpolated color */ interpolate.color = function(from, to, t) { return [ interpolate(from[0], to[0], t), interpolate(from[1], to[1], t), interpolate(from[2], to[2], t), interpolate(from[3], to[3], t) ]; }; interpolate.array = function(from, to, t) { return from.map(function(d, i) { return interpolate(d, to[i], t); }); }; },{}],93:[function(require,module,exports){ 'use strict'; var config = require('./config'); var browser = require('./browser'); function normalizeURL(url, pathPrefix, accessToken) { accessToken = accessToken || config.ACCESS_TOKEN; if (!accessToken && config.REQUIRE_ACCESS_TOKEN) { throw new Error('An API access token is required to use Mapbox GL. ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } var https = config.FORCE_HTTPS || (typeof document !== 'undefined' && document.location.protocol === 'https:'); url = url.replace(/^mapbox:\/\//, (https ? config.HTTPS_URL : config.HTTP_URL) + pathPrefix); url += url.indexOf('?') !== -1 ? '&access_token=' : '?access_token='; if (config.REQUIRE_ACCESS_TOKEN) { if (accessToken[0] === 's') { throw new Error('Use a public access token (pk.*) with Mapbox GL JS, not a secret access token (sk.*). ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } url += accessToken; } return url; } module.exports.normalizeStyleURL = function(url, accessToken) { var user = url.match(/^mapbox:\/\/([^.]+)/); if (!user) return url; return normalizeURL(url, '/styles/v1/' + user[1] + '/', accessToken); }; module.exports.normalizeSourceURL = function(url, accessToken) { if (!url.match(/^mapbox:\/\//)) return url; url = normalizeURL(url + '.json', '/v4/', accessToken); // TileJSON requests need a secure flag appended to their URLs so // that the server knows to send SSL-ified resource references. if (url.indexOf('https') === 0) url += '&secure'; return url; }; module.exports.normalizeGlyphsURL = function(url, accessToken) { if (!url.match(/^mapbox:\/\//)) return url; return normalizeURL(url, '/v4/', accessToken); }; module.exports.normalizeTileURL = function(url, sourceUrl) { if (!sourceUrl || !sourceUrl.match(/^mapbox:\/\//)) return url; return url.replace(/\.((?:png|jpg)\d*)(?=$|\?)/, browser.devicePixelRatio >= 2 ? '@2x.$1' : '.$1'); }; },{"./browser":85,"./config":89}],94:[function(require,module,exports){ 'use strict'; /* * A [most-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms) * with hash lookup made possible by keeping a list of keys in parallel to * an array of dictionary of values * * @param {number} max number of permitted values * @param {Function} onRemove callback called with items when they expire * @private */ module.exports = MRUCache; function MRUCache(max, onRemove) { this.max = max; this.onRemove = onRemove; this.reset(); } /** * Clear the cache * * @returns {MRUCache} this cache */ MRUCache.prototype.reset = function() { for (var key in this.list) { this.onRemove(this.list[key]); } this.list = {}; this.order = []; return this; }; /* * Add a key, value combination to the cache, trimming its size if this pushes * it over max length. * * @param {string} key lookup key for the item * @param {*} data any value * * @returns {MRUCache} this cache */ MRUCache.prototype.add = function(key, data) { this.list[key] = data; this.order.push(key); if (this.order.length > this.max) { var removedData = this.get(this.order[0]); if (removedData) this.onRemove(removedData); } return this; }; /* * Determine whether the value attached to `key` is present * * @param {string} key the key to be looked-up * @returns {boolean} whether the cache has this value */ MRUCache.prototype.has = function(key) { return key in this.list; }; /* * List all keys in the cache * * @returns {Array<string>} an array of keys in this cache. */ MRUCache.prototype.keys = function() { return this.order; }; /* * Get the value attached to a specific key. If the key is not found, * returns `null` * * @param {string} key the key to look up * @returns {*} the data, or null if it isn't found */ MRUCache.prototype.get = function(key) { if (!this.has(key)) { return null; } var data = this.list[key]; delete this.list[key]; this.order.splice(this.order.indexOf(key), 1); return data; }; },{}],95:[function(require,module,exports){ 'use strict'; module.exports = resolveTokens; /** * Replace tokens in a string template with values in an object * * @param {Object} properties a key/value relationship between tokens and replacements * @param {string} text the template string * @returns {string} the template with tokens replaced * @private */ function resolveTokens(properties, text) { return text.replace(/{([^{}()\[\]<>$=:;.,^]+)}/g, function(match, key) { return key in properties ? properties[key] : ''; }); } },{}],96:[function(require,module,exports){ 'use strict'; var UnitBezier = require('unitbezier'); /** * Given a value `t` that varies between 0 and 1, return * an interpolation function that eases between 0 and 1 in a pleasing * cubic in-out fashion. * * @param {number} t input * @returns {number} input */ exports.easeCubicInOut = function (t) { if (t <= 0) return 0; if (t >= 1) return 1; var t2 = t * t, t3 = t2 * t; return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75); }; /** * Given given (x, y), (x1, y1) control points for a bezier curve, * return a function that interpolates along that curve. * * @param {number} p1x control point 1 x coordinate * @param {number} p1y control point 1 y coordinate * @param {number} p2x control point 2 x coordinate * @param {number} p2y control point 2 y coordinate * @returns {Function} interpolator: receives number value, returns * number value. */ exports.bezier = function(p1x, p1y, p2x, p2y) { var bezier = new UnitBezier(p1x, p1y, p2x, p2y); return function(t) { return bezier.solve(t); }; }; /** * A default bezier-curve powered easing function with * control points (0.25, 0.1) and (0.25, 1) * * @param {number} t * @returns {number} output */ exports.ease = exports.bezier(0.25, 0.1, 0.25, 1); /** * Given a four-element array of numbers that represents a color in * RGBA, return a version for which the RGB components are multiplied * by the A (alpha) component * * @param {Number<Array>} c color array * @returns {Number<Array>} premultiplied color array */ exports.premultiply = function (c) { c[0] *= c[3]; c[1] *= c[3]; c[2] *= c[3]; return c; }; /** * constrain n to the given range via min + max * * @param {Number} n value * @param {Number} min the minimum value to be returned * @param {Number} max the maximum value to be returned * @returns {Number} the clamped value */ exports.clamp = function (n, min, max) { return Math.min(max, Math.max(min, n)); }; /* * constrain n to the given range via modular arithmetic * @param {Number} n * @param {Number} min * @param {Number} max * @returns {Number} constrained number */ exports.wrap = function (n, min, max) { var d = max - min; return n === max ? n : ((n - min) % d + d) % d + min; }; /* * return the first non-null and non-undefined argument to this function. * @returns {*} argument */ exports.coalesce = function() { for (var i = 0; i < arguments.length; i++) { var arg = arguments[i]; if (arg !== null && arg !== undefined) return arg; } }; /* * Call an asynchronous function on an array of arguments, * calling `callback` once all calls complete. * * @param {Array<*>} array input to each call of the async function. * @param {Function} fn an async function with signature (data, callback) * @param {Function} callback a callback run after all async work is done. * called with no arguments * @returns {undefined} */ exports.asyncEach = function (array, fn, callback) { var remaining = array.length; if (remaining === 0) return callback(); function check() { if (--remaining === 0) callback(); } for (var i = 0; i < array.length; i++) fn(array[i], check); }; /* * Compute the difference between the keys in one object and the keys * in another object. * * @param {Object} obj * @param {Object} other * @returns {Array<string>} keys difference */ exports.keysDifference = function (obj, other) { var difference = []; for (var i in obj) { if (!(i in other)) { difference.push(i); } } return difference; }; /** * Given a destination object and optionally many source objects, * copy all properties from the source objects into the destination. * The last source object given overrides properties from previous * source objects. * @param {Object} dest destination object * @param {...Object} sources sources from which properties are pulled * @returns {Object} dest */ exports.extend = function (dest) { for (var i = 1; i < arguments.length; i++) { var src = arguments[i]; for (var k in src) { dest[k] = src[k]; } } return dest; }; /** * Extend a destination object with all properties of the src object, * using defineProperty instead of simple assignment. * @param {Object} dest * @param {Object} src * @returns {Object} dest */ exports.extendAll = function (dest, src) { for (var i in src) { Object.defineProperty(dest, i, Object.getOwnPropertyDescriptor(src, i)); } return dest; }; /** * Extend a parent's prototype with all properties in a properties * object. * * @param {Object} parent * @param {Object} props * @returns {Object} */ exports.inherit = function (parent, props) { var parentProto = typeof parent === 'function' ? parent.prototype : parent, proto = Object.create(parentProto); exports.extendAll(proto, props); return proto; }; /** * Given an object and a number of properties as strings, return version * of that object with only those properties. * * @param {Object} src the object * @param {Array<string>} properties an array of property names chosen * to appear on the resulting object. * @returns {Object} object with limited properties. * @example * var foo = { name: 'Charlie', age: 10 }; * var justName = pick(foo, ['name']); * // justName = { name: 'Charlie' } */ exports.pick = function (src, properties) { var result = {}; for (var i = 0; i < properties.length; i++) { var k = properties[i]; if (k in src) { result[k] = src[k]; } } return result; }; var id = 1; /** * Return a unique numeric id, starting at 1 and incrementing with * each call. * * @returns {Number} unique numeric id. */ exports.uniqueId = function () { return id++; }; /** * Create a version of `fn` that only fires once every `time` millseconds. * * @param {Function} fn the function to be throttled * @param {Number} time millseconds required between function calls * @param {*} context the value of `this` with which the function is called * @returns {Function} debounced function */ exports.throttle = function (fn, time, context) { var lock, args, wrapperFn, later; later = function () { // reset lock and call if queued lock = false; if (args) { wrapperFn.apply(context, args); args = false; } }; wrapperFn = function () { if (lock) { // called too soon, queue to call later args = arguments; } else { // call and lock until later fn.apply(context, arguments); setTimeout(later, time); lock = true; } }; return wrapperFn; }; /** * Create a version of `fn` that is only called `time` milliseconds * after its last invocation * * @param {Function} fn the function to be debounced * @param {Number} time millseconds after which the function will be invoked * @returns {Function} debounced function */ exports.debounce = function(fn, time) { var timer, args; return function() { args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn.apply(null, args); }, time); }; }; /** * Given an array of member function names as strings, replace all of them * with bound versions that will always refer to `context` as `this`. This * is useful for classes where otherwise event bindings would reassign * `this` to the evented object or some other value: this lets you ensure * the `this` value always. * * @param {Array<string>} fns list of member function names * @param {*} context the context value * @returns {undefined} changes functions in-place * @example * function MyClass() { * bindAll(['ontimer'], this); * this.name = 'Tom'; * } * MyClass.prototype.ontimer = function() { * alert(this.name); * }; * var myClass = new MyClass(); * setTimeout(myClass.ontimer, 100); */ exports.bindAll = function(fns, context) { fns.forEach(function(fn) { context[fn] = context[fn].bind(context); }); }; /** * Set the 'options' property on `obj` with properties * from the `options` argument. Properties in the `options` * object will override existing properties. * * @param {Object} obj destination object * @param {Object} options object of override options * @returns {Object} derived options object. */ exports.setOptions = function(obj, options) { if (!obj.hasOwnProperty('options')) { obj.options = obj.options ? Object.create(obj.options) : {}; } for (var i in options) { obj.options[i] = options[i]; } return obj.options; }; },{"unitbezier":116}],97:[function(require,module,exports){ // (c) Dean McNamee <dean@gmail.com>, 2012. // // https://github.com/deanm/css-color-parser-js // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // http://www.w3.org/TR/css3-color/ var kCSSColorTable = { "transparent": [0,0,0,0], "aliceblue": [240,248,255,1], "antiquewhite": [250,235,215,1], "aqua": [0,255,255,1], "aquamarine": [127,255,212,1], "azure": [240,255,255,1], "beige": [245,245,220,1], "bisque": [255,228,196,1], "black": [0,0,0,1], "blanchedalmond": [255,235,205,1], "blue": [0,0,255,1], "blueviolet": [138,43,226,1], "brown": [165,42,42,1], "burlywood": [222,184,135,1], "cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1], "chocolate": [210,105,30,1], "coral": [255,127,80,1], "cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1], "crimson": [220,20,60,1], "cyan": [0,255,255,1], "darkblue": [0,0,139,1], "darkcyan": [0,139,139,1], "darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1], "darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1], "darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1], "darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1], "darkorchid": [153,50,204,1], "darkred": [139,0,0,1], "darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1], "darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1], "darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1], "darkviolet": [148,0,211,1], "deeppink": [255,20,147,1], "deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1], "dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1], "firebrick": [178,34,34,1], "floralwhite": [255,250,240,1], "forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1], "gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1], "gold": [255,215,0,1], "goldenrod": [218,165,32,1], "gray": [128,128,128,1], "green": [0,128,0,1], "greenyellow": [173,255,47,1], "grey": [128,128,128,1], "honeydew": [240,255,240,1], "hotpink": [255,105,180,1], "indianred": [205,92,92,1], "indigo": [75,0,130,1], "ivory": [255,255,240,1], "khaki": [240,230,140,1], "lavender": [230,230,250,1], "lavenderblush": [255,240,245,1], "lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1], "lightblue": [173,216,230,1], "lightcoral": [240,128,128,1], "lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1], "lightgray": [211,211,211,1], "lightgreen": [144,238,144,1], "lightgrey": [211,211,211,1], "lightpink": [255,182,193,1], "lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1], "lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1], "lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1], "lightyellow": [255,255,224,1], "lime": [0,255,0,1], "limegreen": [50,205,50,1], "linen": [250,240,230,1], "magenta": [255,0,255,1], "maroon": [128,0,0,1], "mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1], "mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1], "mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1], "mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1], "mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1], "mintcream": [245,255,250,1], "mistyrose": [255,228,225,1], "moccasin": [255,228,181,1], "navajowhite": [255,222,173,1], "navy": [0,0,128,1], "oldlace": [253,245,230,1], "olive": [128,128,0,1], "olivedrab": [107,142,35,1], "orange": [255,165,0,1], "orangered": [255,69,0,1], "orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1], "palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1], "palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1], "peachpuff": [255,218,185,1], "peru": [205,133,63,1], "pink": [255,192,203,1], "plum": [221,160,221,1], "powderblue": [176,224,230,1], "purple": [128,0,128,1], "red": [255,0,0,1], "rosybrown": [188,143,143,1], "royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1], "salmon": [250,128,114,1], "sandybrown": [244,164,96,1], "seagreen": [46,139,87,1], "seashell": [255,245,238,1], "sienna": [160,82,45,1], "silver": [192,192,192,1], "skyblue": [135,206,235,1], "slateblue": [106,90,205,1], "slategray": [112,128,144,1], "slategrey": [112,128,144,1], "snow": [255,250,250,1], "springgreen": [0,255,127,1], "steelblue": [70,130,180,1], "tan": [210,180,140,1], "teal": [0,128,128,1], "thistle": [216,191,216,1], "tomato": [255,99,71,1], "turquoise": [64,224,208,1], "violet": [238,130,238,1], "wheat": [245,222,179,1], "white": [255,255,255,1], "whitesmoke": [245,245,245,1], "yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]} function clamp_css_byte(i) { // Clamp to integer 0 .. 255. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0. return f < 0 ? 0 : f > 1 ? 1 : f; } function parse_css_int(str) { // int or percentage. if (str[str.length - 1] === '%') return clamp_css_byte(parseFloat(str) / 100 * 255); return clamp_css_byte(parseInt(str)); } function parse_css_float(str) { // float or percentage. if (str[str.length - 1] === '%') return clamp_css_float(parseFloat(str) / 100); return clamp_css_float(parseFloat(str)); } function css_hue_to_rgb(m1, m2, h) { if (h < 0) h += 1; else if (h > 1) h -= 1; if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; return m1; } function parseCSSColor(css_str) { // Remove all whitespace, not compliant, but should just be more accepting. var str = css_str.replace(/ /g, '').toLowerCase(); // Color keywords (and transparent) lookup. if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup. // #abc and #abc123 syntax. if (str[0] === '#') { if (str.length === 4) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN. return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), 1]; } else if (str.length === 7) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN. return [(iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, 1]; } return null; } var op = str.indexOf('('), ep = str.indexOf(')'); if (op !== -1 && ep + 1 === str.length) { var fname = str.substr(0, op); var params = str.substr(op+1, ep-(op+1)).split(','); var alpha = 1; // To allow case fallthrough. switch (fname) { case 'rgba': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'rgb': if (params.length !== 3) return null; return [parse_css_int(params[0]), parse_css_int(params[1]), parse_css_int(params[2]), alpha]; case 'hsla': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'hsl': if (params.length !== 3) return null; var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1 // NOTE(deanm): According to the CSS spec s/l should only be // percentages, but we don't bother and let float or percentage. var s = parse_css_float(params[1]); var l = parse_css_float(params[2]); var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; var m1 = l * 2 - m2; return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255), alpha]; default: return null; } } return null; } try { exports.parseCSSColor = parseCSSColor } catch(e) { } },{}],98:[function(require,module,exports){ 'use strict'; var VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon']; function infix(operator) { return function(_, key, value) { if (key === '$type') { return 't' + operator + VectorTileFeatureTypes.indexOf(value); } else { return 'p[' + JSON.stringify(key) + ']' + operator + JSON.stringify(value); } }; } function strictInfix(operator) { var nonstrictInfix = infix(operator); return function(_, key, value) { if (key === '$type') { return nonstrictInfix(_, key, value); } else { return 'typeof(p[' + JSON.stringify(key) + ']) === typeof(' + JSON.stringify(value) + ') && ' + nonstrictInfix(_, key, value); } }; } var operators = { '==': infix('==='), '!=': infix('!=='), '>': strictInfix('>'), '<': strictInfix('<'), '<=': strictInfix('<='), '>=': strictInfix('>='), 'in': function(_, key) { return Array.prototype.slice.call(arguments, 2).map(function(value) { return '(' + operators['=='](_, key, value) + ')'; }).join('||') || 'false'; }, '!in': function() { return '!(' + operators.in.apply(this, arguments) + ')'; }, 'any': function() { return Array.prototype.slice.call(arguments, 1).map(function(filter) { return '(' + compile(filter) + ')'; }).join('||') || 'false'; }, 'all': function() { return Array.prototype.slice.call(arguments, 1).map(function(filter) { return '(' + compile(filter) + ')'; }).join('&&') || 'true'; }, 'none': function() { return '!(' + operators.any.apply(this, arguments) + ')'; } }; function compile(filter) { return operators[filter[0]].apply(filter, filter); } function truth() { return true; } /** * Given a filter expressed as nested arrays, return a new function * that evaluates whether a given feature (with a .properties or .tags property) * passes its test. * * @param {Array} filter mapbox gl filter * @returns {Function} filter-evaluating function */ module.exports = function (filter) { if (!filter) return truth; var filterStr = 'var p = f.properties || f.tags || {}, t = f.type; return ' + compile(filter) + ';'; // jshint evil: true return new Function('f', filterStr); }; },{}],99:[function(require,module,exports){ 'use strict'; module.exports = clip; /* clip features between two axis-parallel lines: * | | * ___|___ | / * / | \____|____/ * | | */ function clip(features, scale, k1, k2, axis, intersect) { k1 /= scale; k2 /= scale; var clipped = []; for (var i = 0; i < features.length; i++) { var feature = features[i], geometry = feature.geometry, type = feature.type, min, max; if (feature.min) { min = feature.min[axis]; max = feature.max[axis]; if (min >= k1 && max <= k2) { // trivial accept clipped.push(feature); continue; } else if (min > k2 || max < k1) continue; // trivial reject } var slices = type === 1 ? clipPoints(geometry, k1, k2, axis) : clipGeometry(geometry, k1, k2, axis, intersect, type === 3); if (slices.length) { // if a feature got clipped, it will likely get clipped on the next zoom level as well, // so there's no need to recalculate bboxes clipped.push({ geometry: slices, type: type, tags: features[i].tags || null }); } } return clipped.length ? clipped : null; } function clipPoints(geometry, k1, k2, axis) { var slice = []; for (var i = 0; i < geometry.length; i++) { var a = geometry[i], ak = a[axis]; if (ak >= k1 && ak <= k2) slice.push(a); } return slice; } function clipGeometry(geometry, k1, k2, axis, intersect, closed) { var slices = []; for (var i = 0; i < geometry.length; i++) { var ak = 0, bk = 0, b = null, points = geometry[i], area = points.area, dist = points.dist, len = points.length, a, j; var slice = []; for (j = 0; j < len - 1; j++) { a = b || points[j]; b = points[j + 1]; ak = bk || a[axis]; bk = b[axis]; if (ak < k1) { if ((bk > k2)) { // ---|-----|--> slice.push(intersect(a, b, k1), intersect(a, b, k2)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk >= k1) slice.push(intersect(a, b, k1)); // ---|--> | } else if (ak > k2) { if ((bk < k1)) { // <--|-----|--- slice.push(intersect(a, b, k2), intersect(a, b, k1)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk <= k2) slice.push(intersect(a, b, k2)); // | <--|--- } else { slice.push(a); if (bk < k1) { // <--|--- | slice.push(intersect(a, b, k1)); if (!closed) slice = newSlice(slices, slice, area, dist); } else if (bk > k2) { // | ---|--> slice.push(intersect(a, b, k2)); if (!closed) slice = newSlice(slices, slice, area, dist); } // | --> | } } // add the last point a = points[len - 1]; ak = a[axis]; if (ak >= k1 && ak <= k2) slice.push(a); // close the polygon if its endpoints are not the same after clipping if (closed && slice[0] !== slice[slice.length - 1]) slice.push(slice[0]); // add the final slice newSlice(slices, slice, area, dist); } return slices; } function newSlice(slices, slice, area, dist) { if (slice.length) { // we don't recalculate the area/length of the unclipped geometry because the case where it goes // below the visibility threshold as a result of clipping is rare, so we avoid doing unnecessary work slice.area = area; slice.dist = dist; slices.push(slice); } return []; } },{}],100:[function(require,module,exports){ 'use strict'; module.exports = convert; var simplify = require('./simplify'); // converts GeoJSON feature into an intermediate projected JSON vector format with simplification data function convert(data, tolerance) { var features = []; if (data.type === 'FeatureCollection') { for (var i = 0; i < data.features.length; i++) { convertFeature(features, data.features[i], tolerance); } } else if (data.type === 'Feature') { convertFeature(features, data, tolerance); } else { // single geometry or a geometry collection convertFeature(features, {geometry: data}, tolerance); } return features; } function convertFeature(features, feature, tolerance) { var geom = feature.geometry, type = geom.type, coords = geom.coordinates, tags = feature.properties, i, j, rings; if (type === 'Point') { features.push(create(tags, 1, [projectPoint(coords)])); } else if (type === 'MultiPoint') { features.push(create(tags, 1, project(coords))); } else if (type === 'LineString') { features.push(create(tags, 2, [project(coords, tolerance)])); } else if (type === 'MultiLineString' || type === 'Polygon') { rings = []; for (i = 0; i < coords.length; i++) { rings.push(project(coords[i], tolerance)); } features.push(create(tags, type === 'Polygon' ? 3 : 2, rings)); } else if (type === 'MultiPolygon') { rings = []; for (i = 0; i < coords.length; i++) { for (j = 0; j < coords[i].length; j++) { rings.push(project(coords[i][j], tolerance)); } } features.push(create(tags, 3, rings)); } else if (type === 'GeometryCollection') { for (i = 0; i < geom.geometries.length; i++) { convertFeature(features, { geometry: geom.geometries[i], properties: tags }, tolerance); } } else { console.warn('Unsupported GeoJSON type: ' + geom.type); } } function create(tags, type, geometry) { var feature = { geometry: geometry, type: type, tags: tags || null, min: [1, 1], // initial bbox values; max: [0, 0] // note that all coords are in [0..1] range }; calcBBox(feature); return feature; } function project(lonlats, tolerance) { var projected = []; for (var i = 0; i < lonlats.length; i++) { projected.push(projectPoint(lonlats[i])); } if (tolerance) { simplify(projected, tolerance); calcSize(projected); } return projected; } function projectPoint(p) { var sin = Math.sin(p[1] * Math.PI / 180), x = (p[0] / 360 + 0.5), y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI); return [x, y, 0]; } // calculate area and length of the poly function calcSize(points) { var area = 0, dist = 0; for (var i = 0, a, b; i < points.length - 1; i++) { a = b || points[i]; b = points[i + 1]; area += a[0] * b[1] - b[0] * a[1]; // use Manhattan distance instead of Euclidian one to avoid expensive square root computation dist += Math.abs(b[0] - a[0]) + Math.abs(b[1] - a[1]); } points.area = Math.abs(area / 2); points.dist = dist; } // calculate the feature bounding box for faster clipping later function calcBBox(feature) { var geometry = feature.geometry, min = feature.min, max = feature.max; if (feature.type === 1) calcRingBBox(min, max, geometry); else for (var i = 0; i < geometry.length; i++) calcRingBBox(min, max, geometry[i]); return feature; } function calcRingBBox(min, max, points) { for (var i = 0, p; i < points.length; i++) { p = points[i]; min[0] = Math.min(p[0], min[0]); max[0] = Math.max(p[0], max[0]); min[1] = Math.min(p[1], min[1]); max[1] = Math.max(p[1], max[1]); } } },{"./simplify":102}],101:[function(require,module,exports){ 'use strict'; module.exports = geojsonvt; var convert = require('./convert'), // GeoJSON conversion and preprocessing clip = require('./clip'), // stripe clipping algorithm createTile = require('./tile'); // final simplified tile generation function geojsonvt(data, options) { return new GeoJSONVT(data, options); } function GeoJSONVT(data, options) { options = this.options = extend(Object.create(this.options), options); var debug = options.debug; if (debug) console.time('preprocess data'); var z2 = 1 << options.baseZoom, // 2^z features = convert(data, options.tolerance / (z2 * options.extent)); this.tiles = {}; if (debug) { console.timeEnd('preprocess data'); console.time('generate tiles up to z' + options.maxZoom); this.stats = {}; this.total = 0; } // start slicing from the top tile down this.splitTile(features, 0, 0, 0); if (debug) { console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints); console.timeEnd('generate tiles up to z' + options.maxZoom); console.log('tiles generated:', this.total, JSON.stringify(this.stats)); } } GeoJSONVT.prototype.options = { baseZoom: 14, // max zoom to preserve detail on maxZoom: 4, // zoom to slice down to on first pass maxPoints: 100, // stop slicing a tile below this number of points tolerance: 3, // simplification tolerance (higher means simpler) extent: 4096, // tile extent buffer: 64, // tile buffer on each side debug: 0 // logging level (0, 1 or 2) }; GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) { var stack = [features, z, x, y], options = this.options, debug = options.debug, extent = options.extent, buffer = options.buffer; // avoid recursion by using a processing queue while (stack.length) { features = stack.shift(); z = stack.shift(); x = stack.shift(); y = stack.shift(); var z2 = 1 << z, id = toID(z, x, y), tile = this.tiles[id], tileTolerance = z === options.baseZoom ? 0 : options.tolerance / (z2 * extent); if (!tile) { if (debug > 1) console.time('creation'); tile = this.tiles[id] = createTile(features, z2, x, y, tileTolerance, extent, z === options.baseZoom); if (debug) { if (debug > 1) { console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)', z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified); console.timeEnd('creation'); } var key = 'z' + z + ':'; this.stats[key] = (this.stats[key] || 0) + 1; this.total++; } } if (!cz && (z === options.maxZoom || tile.numPoints <= options.maxPoints || isClippedSquare(tile.features, extent, buffer)) || z === options.baseZoom || z === cz) { tile.source = features; continue; // stop tiling } if (cz) tile.source = features; else tile.source = null; if (debug > 1) console.time('clipping'); // values we'll use for clipping var k1 = 0.5 * buffer / extent, k2 = 0.5 - k1, k3 = 0.5 + k1, k4 = 1 + k1, tl, bl, tr, br, left, right, m, goLeft, goTop; if (cz) { // if we have a specific tile to drill down to, calculate where to go m = 1 << (cz - z); goLeft = cx / m - x < 0.5; goTop = cy / m - y < 0.5; } tl = bl = tr = br = left = right = null; if (!cz || goLeft) left = clip(features, z2, x - k1, x + k3, 0, intersectX); if (!cz || !goLeft) right = clip(features, z2, x + k2, x + k4, 0, intersectX); if (left) { if (!cz || goTop) tl = clip(left, z2, y - k1, y + k3, 1, intersectY); if (!cz || !goTop) bl = clip(left, z2, y + k2, y + k4, 1, intersectY); } if (right) { if (!cz || goTop) tr = clip(right, z2, y - k1, y + k3, 1, intersectY); if (!cz || !goTop) br = clip(right, z2, y + k2, y + k4, 1, intersectY); } if (debug > 1) console.timeEnd('clipping'); if (tl) stack.push(tl, z + 1, x * 2, y * 2); if (bl) stack.push(bl, z + 1, x * 2, y * 2 + 1); if (tr) stack.push(tr, z + 1, x * 2 + 1, y * 2); if (br) stack.push(br, z + 1, x * 2 + 1, y * 2 + 1); } }; GeoJSONVT.prototype.getTile = function (z, x, y) { var id = toID(z, x, y); if (this.tiles[id]) return this.tiles[id]; var options = this.options, debug = options.debug; if (debug > 1) console.log('drilling down to z%d-%d-%d', z, x, y); var z0 = z, x0 = x, y0 = y, parent; while (!parent && z0 > 0) { z0--; x0 = Math.floor(x0 / 2); y0 = Math.floor(y0 / 2); parent = this.tiles[toID(z0, x0, y0)]; } if (debug > 1) console.log('found parent tile z%d-%d-%d', z0, x0, y0); // if we found a parent tile containing the original geometry, we can drill down from it if (parent.source) { if (isClippedSquare(parent.features, options.extent, options.buffer)) return parent; if (debug) console.time('drilling down'); this.splitTile(parent.source, z0, x0, y0, z, x, y); if (debug) console.timeEnd('drilling down'); } return this.tiles[id]; }; // checks whether a tile is a whole-area fill after clipping; if it is, there's no sense slicing it further function isClippedSquare(features, extent, buffer) { if (features.length !== 1) return false; var feature = features[0]; if (feature.type !== 3 || feature.geometry.length > 1) return false; for (var i = 0; i < feature.geometry[0].length; i++) { var p = feature.geometry[0][i]; if ((p[0] !== -buffer && p[0] !== extent + buffer) || (p[1] !== -buffer && p[1] !== extent + buffer)) return false; } return true; } function toID(z, x, y) { return (((1 << z) * y + x) * 32) + z; } function intersectX(a, b, x) { return [x, (x - a[0]) * (b[1] - a[1]) / (b[0] - a[0]) + a[1], 1]; } function intersectY(a, b, y) { return [(y - a[1]) * (b[0] - a[0]) / (b[1] - a[1]) + a[0], y, 1]; } function extend(dest, src) { for (var i in src) dest[i] = src[i]; return dest; } },{"./clip":99,"./convert":100,"./tile":103}],102:[function(require,module,exports){ 'use strict'; module.exports = simplify; // calculate simplification data using optimized Douglas-Peucker algorithm function simplify(points, tolerance) { var sqTolerance = tolerance * tolerance, len = points.length, first = 0, last = len - 1, stack = [], i, maxSqDist, sqDist, index; // always retain the endpoints (1 is the max value) points[first][2] = 1; points[last][2] = 1; // avoid recursion by using a stack while (last) { maxSqDist = 0; for (i = first + 1; i < last; i++) { sqDist = getSqSegDist(points[i], points[first], points[last]); if (sqDist > maxSqDist) { index = i; maxSqDist = sqDist; } } if (maxSqDist > sqTolerance) { points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate stack.push(first, index, index, last); } last = stack.pop(); first = stack.pop(); } } // square distance from a point to a segment function getSqSegDist(p, a, b) { var x = a[0], y = a[1], bx = b[0], by = b[1], px = p[0], py = p[1], dx = bx - x, dy = by - y; if (dx !== 0 || dy !== 0) { var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy); if (t > 1) { x = bx; y = by; } else if (t > 0) { x += dx * t; y += dy * t; } } dx = px - x; dy = py - y; return dx * dx + dy * dy; } },{}],103:[function(require,module,exports){ 'use strict'; module.exports = createTile; function createTile(features, z2, tx, ty, tolerance, extent, noSimplify) { var tile = { features: [], numPoints: 0, numSimplified: 0, numFeatures: 0, source: null }; for (var i = 0; i < features.length; i++) { tile.numFeatures++; addFeature(tile, features[i], z2, tx, ty, tolerance, extent, noSimplify); } return tile; } function addFeature(tile, feature, z2, tx, ty, tolerance, extent, noSimplify) { var geom = feature.geometry, type = feature.type, transformed = [], sqTolerance = tolerance * tolerance, i, j, ring, p; if (type === 1) { for (i = 0; i < geom.length; i++) { transformed.push(transformPoint(geom[i], z2, tx, ty, extent)); tile.numPoints++; tile.numSimplified++; } } else { // simplify and transform projected coordinates for tile geometry for (i = 0; i < geom.length; i++) { ring = geom[i]; // filter out tiny polylines & polygons if (!noSimplify && ((type === 2 && ring.dist < tolerance) || (type === 3 && ring.area < sqTolerance))) { tile.numPoints += ring.length; continue; } var transformedRing = []; for (j = 0; j < ring.length; j++) { p = ring[j]; // keep points with importance > tolerance if (noSimplify || p[2] > sqTolerance) { transformedRing.push(transformPoint(p, z2, tx, ty, extent)); tile.numSimplified++; } tile.numPoints++; } transformed.push(transformedRing); } } if (transformed.length) { tile.features.push({ geometry: transformed, type: type, tags: feature.tags || null }); } } function transformPoint(p, z2, tx, ty, extent) { var x = Math.round(extent * (p[0] * z2 - tx)), y = Math.round(extent * (p[1] * z2 - ty)); return [x, y]; } },{}],104:[function(require,module,exports){ /** * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV * @version 2.2.1 */ /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function(_global) { "use strict"; var shim = {}; if (typeof(exports) === 'undefined') { if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) { shim.exports = {}; define(function() { return shim.exports; }); } else { // gl-matrix lives in a browser, define its namespaces in global shim.exports = typeof(window) !== 'undefined' ? window : _global; } } else { // gl-matrix lives in commonjs, define its namespaces in exports shim.exports = exports; } (function(exports) { /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ if(!GLMAT_EPSILON) { var GLMAT_EPSILON = 0.000001; } if(!GLMAT_ARRAY_TYPE) { var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array; } if(!GLMAT_RANDOM) { var GLMAT_RANDOM = Math.random; } /** * @class Common utilities * @name glMatrix */ var glMatrix = {}; /** * Sets the type of array used when creating new vectors and matricies * * @param {Type} type Array type, such as Float32Array or Array */ glMatrix.setMatrixArrayType = function(type) { GLMAT_ARRAY_TYPE = type; } if(typeof(exports) !== 'undefined') { exports.glMatrix = glMatrix; } var degree = Math.PI / 180; /** * Convert Degree To Radian * * @param {Number} Angle in Degrees */ glMatrix.toRadian = function(a){ return a * degree; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2 Dimensional Vector * @name vec2 */ var vec2 = {}; /** * Creates a new, empty vec2 * * @returns {vec2} a new 2D vector */ vec2.create = function() { var out = new GLMAT_ARRAY_TYPE(2); out[0] = 0; out[1] = 0; return out; }; /** * Creates a new vec2 initialized with values from an existing vector * * @param {vec2} a vector to clone * @returns {vec2} a new 2D vector */ vec2.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(2); out[0] = a[0]; out[1] = a[1]; return out; }; /** * Creates a new vec2 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @returns {vec2} a new 2D vector */ vec2.fromValues = function(x, y) { var out = new GLMAT_ARRAY_TYPE(2); out[0] = x; out[1] = y; return out; }; /** * Copy the values from one vec2 to another * * @param {vec2} out the receiving vector * @param {vec2} a the source vector * @returns {vec2} out */ vec2.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; return out; }; /** * Set the components of a vec2 to the given values * * @param {vec2} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @returns {vec2} out */ vec2.set = function(out, x, y) { out[0] = x; out[1] = y; return out; }; /** * Adds two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; return out; }; /** * Subtracts vector b from vector a * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; return out; }; /** * Alias for {@link vec2.subtract} * @function */ vec2.sub = vec2.subtract; /** * Multiplies two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; return out; }; /** * Alias for {@link vec2.multiply} * @function */ vec2.mul = vec2.multiply; /** * Divides two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; return out; }; /** * Alias for {@link vec2.divide} * @function */ vec2.div = vec2.divide; /** * Returns the minimum of two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); return out; }; /** * Returns the maximum of two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ vec2.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); return out; }; /** * Scales a vec2 by a scalar number * * @param {vec2} out the receiving vector * @param {vec2} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec2} out */ vec2.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; return out; }; /** * Adds two vec2's after scaling the second operand by a scalar value * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec2} out */ vec2.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); return out; }; /** * Calculates the euclidian distance between two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} distance between a and b */ vec2.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1]; return Math.sqrt(x*x + y*y); }; /** * Alias for {@link vec2.distance} * @function */ vec2.dist = vec2.distance; /** * Calculates the squared euclidian distance between two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} squared distance between a and b */ vec2.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1]; return x*x + y*y; }; /** * Alias for {@link vec2.squaredDistance} * @function */ vec2.sqrDist = vec2.squaredDistance; /** * Calculates the length of a vec2 * * @param {vec2} a vector to calculate length of * @returns {Number} length of a */ vec2.length = function (a) { var x = a[0], y = a[1]; return Math.sqrt(x*x + y*y); }; /** * Alias for {@link vec2.length} * @function */ vec2.len = vec2.length; /** * Calculates the squared length of a vec2 * * @param {vec2} a vector to calculate squared length of * @returns {Number} squared length of a */ vec2.squaredLength = function (a) { var x = a[0], y = a[1]; return x*x + y*y; }; /** * Alias for {@link vec2.squaredLength} * @function */ vec2.sqrLen = vec2.squaredLength; /** * Negates the components of a vec2 * * @param {vec2} out the receiving vector * @param {vec2} a vector to negate * @returns {vec2} out */ vec2.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; return out; }; /** * Normalize a vec2 * * @param {vec2} out the receiving vector * @param {vec2} a vector to normalize * @returns {vec2} out */ vec2.normalize = function(out, a) { var x = a[0], y = a[1]; var len = x*x + y*y; if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; } return out; }; /** * Calculates the dot product of two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} dot product of a and b */ vec2.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1]; }; /** * Computes the cross product of two vec2's * Note that the cross product must by definition produce a 3D vector * * @param {vec3} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec3} out */ vec2.cross = function(out, a, b) { var z = a[0] * b[1] - a[1] * b[0]; out[0] = out[1] = 0; out[2] = z; return out; }; /** * Performs a linear interpolation between two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec2} out */ vec2.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); return out; }; /** * Generates a random vector with the given scale * * @param {vec2} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec2} out */ vec2.random = function (out, scale) { scale = scale || 1.0; var r = GLMAT_RANDOM() * 2.0 * Math.PI; out[0] = Math.cos(r) * scale; out[1] = Math.sin(r) * scale; return out; }; /** * Transforms the vec2 with a mat2 * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat2} m matrix to transform with * @returns {vec2} out */ vec2.transformMat2 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[2] * y; out[1] = m[1] * x + m[3] * y; return out; }; /** * Transforms the vec2 with a mat2d * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat2d} m matrix to transform with * @returns {vec2} out */ vec2.transformMat2d = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[2] * y + m[4]; out[1] = m[1] * x + m[3] * y + m[5]; return out; }; /** * Transforms the vec2 with a mat3 * 3rd vector component is implicitly '1' * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat3} m matrix to transform with * @returns {vec2} out */ vec2.transformMat3 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[3] * y + m[6]; out[1] = m[1] * x + m[4] * y + m[7]; return out; }; /** * Transforms the vec2 with a mat4 * 3rd vector component is implicitly '0' * 4th vector component is implicitly '1' * * @param {vec2} out the receiving vector * @param {vec2} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec2} out */ vec2.transformMat4 = function(out, a, m) { var x = a[0], y = a[1]; out[0] = m[0] * x + m[4] * y + m[12]; out[1] = m[1] * x + m[5] * y + m[13]; return out; }; /** * Perform some operation over an array of vec2s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec2.forEach = (function() { var vec = vec2.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 2; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec2} vec vector to represent as a string * @returns {String} string representation of the vector */ vec2.str = function (a) { return 'vec2(' + a[0] + ', ' + a[1] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec2 = vec2; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 3 Dimensional Vector * @name vec3 */ var vec3 = {}; /** * Creates a new, empty vec3 * * @returns {vec3} a new 3D vector */ vec3.create = function() { var out = new GLMAT_ARRAY_TYPE(3); out[0] = 0; out[1] = 0; out[2] = 0; return out; }; /** * Creates a new vec3 initialized with values from an existing vector * * @param {vec3} a vector to clone * @returns {vec3} a new 3D vector */ vec3.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(3); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; }; /** * Creates a new vec3 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} a new 3D vector */ vec3.fromValues = function(x, y, z) { var out = new GLMAT_ARRAY_TYPE(3); out[0] = x; out[1] = y; out[2] = z; return out; }; /** * Copy the values from one vec3 to another * * @param {vec3} out the receiving vector * @param {vec3} a the source vector * @returns {vec3} out */ vec3.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; }; /** * Set the components of a vec3 to the given values * * @param {vec3} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} out */ vec3.set = function(out, x, y, z) { out[0] = x; out[1] = y; out[2] = z; return out; }; /** * Adds two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; return out; }; /** * Subtracts vector b from vector a * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; return out; }; /** * Alias for {@link vec3.subtract} * @function */ vec3.sub = vec3.subtract; /** * Multiplies two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; out[2] = a[2] * b[2]; return out; }; /** * Alias for {@link vec3.multiply} * @function */ vec3.mul = vec3.multiply; /** * Divides two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; out[2] = a[2] / b[2]; return out; }; /** * Alias for {@link vec3.divide} * @function */ vec3.div = vec3.divide; /** * Returns the minimum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); out[2] = Math.min(a[2], b[2]); return out; }; /** * Returns the maximum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); out[2] = Math.max(a[2], b[2]); return out; }; /** * Scales a vec3 by a scalar number * * @param {vec3} out the receiving vector * @param {vec3} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec3} out */ vec3.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; return out; }; /** * Adds two vec3's after scaling the second operand by a scalar value * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec3} out */ vec3.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); out[2] = a[2] + (b[2] * scale); return out; }; /** * Calculates the euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} distance between a and b */ vec3.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2]; return Math.sqrt(x*x + y*y + z*z); }; /** * Alias for {@link vec3.distance} * @function */ vec3.dist = vec3.distance; /** * Calculates the squared euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} squared distance between a and b */ vec3.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2]; return x*x + y*y + z*z; }; /** * Alias for {@link vec3.squaredDistance} * @function */ vec3.sqrDist = vec3.squaredDistance; /** * Calculates the length of a vec3 * * @param {vec3} a vector to calculate length of * @returns {Number} length of a */ vec3.length = function (a) { var x = a[0], y = a[1], z = a[2]; return Math.sqrt(x*x + y*y + z*z); }; /** * Alias for {@link vec3.length} * @function */ vec3.len = vec3.length; /** * Calculates the squared length of a vec3 * * @param {vec3} a vector to calculate squared length of * @returns {Number} squared length of a */ vec3.squaredLength = function (a) { var x = a[0], y = a[1], z = a[2]; return x*x + y*y + z*z; }; /** * Alias for {@link vec3.squaredLength} * @function */ vec3.sqrLen = vec3.squaredLength; /** * Negates the components of a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to negate * @returns {vec3} out */ vec3.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; return out; }; /** * Normalize a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to normalize * @returns {vec3} out */ vec3.normalize = function(out, a) { var x = a[0], y = a[1], z = a[2]; var len = x*x + y*y + z*z; if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; out[2] = a[2] * len; } return out; }; /** * Calculates the dot product of two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} dot product of a and b */ vec3.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }; /** * Computes the cross product of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ vec3.cross = function(out, a, b) { var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2]; out[0] = ay * bz - az * by; out[1] = az * bx - ax * bz; out[2] = ax * by - ay * bx; return out; }; /** * Performs a linear interpolation between two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec3} out */ vec3.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1], az = a[2]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); return out; }; /** * Generates a random vector with the given scale * * @param {vec3} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec3} out */ vec3.random = function (out, scale) { scale = scale || 1.0; var r = GLMAT_RANDOM() * 2.0 * Math.PI; var z = (GLMAT_RANDOM() * 2.0) - 1.0; var zScale = Math.sqrt(1.0-z*z) * scale; out[0] = Math.cos(r) * zScale; out[1] = Math.sin(r) * zScale; out[2] = z * scale; return out; }; /** * Transforms the vec3 with a mat4. * 4th vector component is implicitly '1' * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec3} out */ vec3.transformMat4 = function(out, a, m) { var x = a[0], y = a[1], z = a[2]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; return out; }; /** * Transforms the vec3 with a mat3. * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m the 3x3 matrix to transform with * @returns {vec3} out */ vec3.transformMat3 = function(out, a, m) { var x = a[0], y = a[1], z = a[2]; out[0] = x * m[0] + y * m[3] + z * m[6]; out[1] = x * m[1] + y * m[4] + z * m[7]; out[2] = x * m[2] + y * m[5] + z * m[8]; return out; }; /** * Transforms the vec3 with a quat * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {quat} q quaternion to transform with * @returns {vec3} out */ vec3.transformQuat = function(out, a, q) { // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations var x = a[0], y = a[1], z = a[2], qx = q[0], qy = q[1], qz = q[2], qw = q[3], // calculate quat * vec ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; return out; }; /* * Rotate a 3D vector around the x-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateX = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[0]; r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c); r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c); //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /* * Rotate a 3D vector around the y-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateY = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c); r[1] = p[1]; r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c); //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /* * Rotate a 3D vector around the z-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ vec3.rotateZ = function(out, a, b, c){ var p = [], r=[]; //Translate point to the origin p[0] = a[0] - b[0]; p[1] = a[1] - b[1]; p[2] = a[2] - b[2]; //perform rotation r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c); r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c); r[2] = p[2]; //translate to correct position out[0] = r[0] + b[0]; out[1] = r[1] + b[1]; out[2] = r[2] + b[2]; return out; }; /** * Perform some operation over an array of vec3s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec3.forEach = (function() { var vec = vec3.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 3; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec3} vec vector to represent as a string * @returns {String} string representation of the vector */ vec3.str = function (a) { return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec3 = vec3; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 4 Dimensional Vector * @name vec4 */ var vec4 = {}; /** * Creates a new, empty vec4 * * @returns {vec4} a new 4D vector */ vec4.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; return out; }; /** * Creates a new vec4 initialized with values from an existing vector * * @param {vec4} a vector to clone * @returns {vec4} a new 4D vector */ vec4.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Creates a new vec4 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {vec4} a new 4D vector */ vec4.fromValues = function(x, y, z, w) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out; }; /** * Copy the values from one vec4 to another * * @param {vec4} out the receiving vector * @param {vec4} a the source vector * @returns {vec4} out */ vec4.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Set the components of a vec4 to the given values * * @param {vec4} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {vec4} out */ vec4.set = function(out, x, y, z, w) { out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out; }; /** * Adds two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.add = function(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; return out; }; /** * Subtracts vector b from vector a * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.subtract = function(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; out[3] = a[3] - b[3]; return out; }; /** * Alias for {@link vec4.subtract} * @function */ vec4.sub = vec4.subtract; /** * Multiplies two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.multiply = function(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; out[2] = a[2] * b[2]; out[3] = a[3] * b[3]; return out; }; /** * Alias for {@link vec4.multiply} * @function */ vec4.mul = vec4.multiply; /** * Divides two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.divide = function(out, a, b) { out[0] = a[0] / b[0]; out[1] = a[1] / b[1]; out[2] = a[2] / b[2]; out[3] = a[3] / b[3]; return out; }; /** * Alias for {@link vec4.divide} * @function */ vec4.div = vec4.divide; /** * Returns the minimum of two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.min = function(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); out[2] = Math.min(a[2], b[2]); out[3] = Math.min(a[3], b[3]); return out; }; /** * Returns the maximum of two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {vec4} out */ vec4.max = function(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); out[2] = Math.max(a[2], b[2]); out[3] = Math.max(a[3], b[3]); return out; }; /** * Scales a vec4 by a scalar number * * @param {vec4} out the receiving vector * @param {vec4} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec4} out */ vec4.scale = function(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; return out; }; /** * Adds two vec4's after scaling the second operand by a scalar value * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec4} out */ vec4.scaleAndAdd = function(out, a, b, scale) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); out[2] = a[2] + (b[2] * scale); out[3] = a[3] + (b[3] * scale); return out; }; /** * Calculates the euclidian distance between two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} distance between a and b */ vec4.distance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3]; return Math.sqrt(x*x + y*y + z*z + w*w); }; /** * Alias for {@link vec4.distance} * @function */ vec4.dist = vec4.distance; /** * Calculates the squared euclidian distance between two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} squared distance between a and b */ vec4.squaredDistance = function(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3]; return x*x + y*y + z*z + w*w; }; /** * Alias for {@link vec4.squaredDistance} * @function */ vec4.sqrDist = vec4.squaredDistance; /** * Calculates the length of a vec4 * * @param {vec4} a vector to calculate length of * @returns {Number} length of a */ vec4.length = function (a) { var x = a[0], y = a[1], z = a[2], w = a[3]; return Math.sqrt(x*x + y*y + z*z + w*w); }; /** * Alias for {@link vec4.length} * @function */ vec4.len = vec4.length; /** * Calculates the squared length of a vec4 * * @param {vec4} a vector to calculate squared length of * @returns {Number} squared length of a */ vec4.squaredLength = function (a) { var x = a[0], y = a[1], z = a[2], w = a[3]; return x*x + y*y + z*z + w*w; }; /** * Alias for {@link vec4.squaredLength} * @function */ vec4.sqrLen = vec4.squaredLength; /** * Negates the components of a vec4 * * @param {vec4} out the receiving vector * @param {vec4} a vector to negate * @returns {vec4} out */ vec4.negate = function(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = -a[3]; return out; }; /** * Normalize a vec4 * * @param {vec4} out the receiving vector * @param {vec4} a vector to normalize * @returns {vec4} out */ vec4.normalize = function(out, a) { var x = a[0], y = a[1], z = a[2], w = a[3]; var len = x*x + y*y + z*z + w*w; if (len > 0) { len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; out[2] = a[2] * len; out[3] = a[3] * len; } return out; }; /** * Calculates the dot product of two vec4's * * @param {vec4} a the first operand * @param {vec4} b the second operand * @returns {Number} dot product of a and b */ vec4.dot = function (a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; }; /** * Performs a linear interpolation between two vec4's * * @param {vec4} out the receiving vector * @param {vec4} a the first operand * @param {vec4} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec4} out */ vec4.lerp = function (out, a, b, t) { var ax = a[0], ay = a[1], az = a[2], aw = a[3]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); out[3] = aw + t * (b[3] - aw); return out; }; /** * Generates a random vector with the given scale * * @param {vec4} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec4} out */ vec4.random = function (out, scale) { scale = scale || 1.0; //TODO: This is a pretty awful way of doing this. Find something better. out[0] = GLMAT_RANDOM(); out[1] = GLMAT_RANDOM(); out[2] = GLMAT_RANDOM(); out[3] = GLMAT_RANDOM(); vec4.normalize(out, out); vec4.scale(out, out, scale); return out; }; /** * Transforms the vec4 with a mat4. * * @param {vec4} out the receiving vector * @param {vec4} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec4} out */ vec4.transformMat4 = function(out, a, m) { var x = a[0], y = a[1], z = a[2], w = a[3]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; return out; }; /** * Transforms the vec4 with a quat * * @param {vec4} out the receiving vector * @param {vec4} a the vector to transform * @param {quat} q quaternion to transform with * @returns {vec4} out */ vec4.transformQuat = function(out, a, q) { var x = a[0], y = a[1], z = a[2], qx = q[0], qy = q[1], qz = q[2], qw = q[3], // calculate quat * vec ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; return out; }; /** * Perform some operation over an array of vec4s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ vec4.forEach = (function() { var vec = vec4.create(); return function(a, stride, offset, count, fn, arg) { var i, l; if(!stride) { stride = 4; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; } return a; }; })(); /** * Returns a string representation of a vector * * @param {vec4} vec vector to represent as a string * @returns {String} string representation of the vector */ vec4.str = function (a) { return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; if(typeof(exports) !== 'undefined') { exports.vec4 = vec4; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2x2 Matrix * @name mat2 */ var mat2 = {}; /** * Creates a new identity mat2 * * @returns {mat2} a new 2x2 matrix */ mat2.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Creates a new mat2 initialized with values from an existing matrix * * @param {mat2} a matrix to clone * @returns {mat2} a new 2x2 matrix */ mat2.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(4); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Copy the values from one mat2 to another * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; }; /** * Set a mat2 to the identity matrix * * @param {mat2} out the receiving matrix * @returns {mat2} out */ mat2.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Transpose the values of a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a1 = a[1]; out[1] = a[2]; out[2] = a1; } else { out[0] = a[0]; out[1] = a[2]; out[2] = a[1]; out[3] = a[3]; } return out; }; /** * Inverts a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.invert = function(out, a) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], // Calculate the determinant det = a0 * a3 - a2 * a1; if (!det) { return null; } det = 1.0 / det; out[0] = a3 * det; out[1] = -a1 * det; out[2] = -a2 * det; out[3] = a0 * det; return out; }; /** * Calculates the adjugate of a mat2 * * @param {mat2} out the receiving matrix * @param {mat2} a the source matrix * @returns {mat2} out */ mat2.adjoint = function(out, a) { // Caching this value is nessecary if out == a var a0 = a[0]; out[0] = a[3]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a0; return out; }; /** * Calculates the determinant of a mat2 * * @param {mat2} a the source matrix * @returns {Number} determinant of a */ mat2.determinant = function (a) { return a[0] * a[3] - a[2] * a[1]; }; /** * Multiplies two mat2's * * @param {mat2} out the receiving matrix * @param {mat2} a the first operand * @param {mat2} b the second operand * @returns {mat2} out */ mat2.multiply = function (out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; return out; }; /** * Alias for {@link mat2.multiply} * @function */ mat2.mul = mat2.multiply; /** * Rotates a mat2 by the given angle * * @param {mat2} out the receiving matrix * @param {mat2} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2} out */ mat2.rotate = function (out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], s = Math.sin(rad), c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; return out; }; /** * Scales the mat2 by the dimensions in the given vec2 * * @param {mat2} out the receiving matrix * @param {mat2} a the matrix to rotate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat2} out **/ mat2.scale = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; return out; }; /** * Returns a string representation of a mat2 * * @param {mat2} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat2.str = function (a) { return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; /** * Returns Frobenius norm of a mat2 * * @param {mat2} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat2.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2))) }; /** * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix * @param {mat2} L the lower triangular matrix * @param {mat2} D the diagonal matrix * @param {mat2} U the upper triangular matrix * @param {mat2} a the input matrix to factorize */ mat2.LDU = function (L, D, U, a) { L[2] = a[2]/a[0]; U[0] = a[0]; U[1] = a[1]; U[3] = a[3] - L[2] * U[1]; return [L, D, U]; }; if(typeof(exports) !== 'undefined') { exports.mat2 = mat2; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 2x3 Matrix * @name mat2d * * @description * A mat2d contains six elements defined as: * <pre> * [a, c, tx, * b, d, ty] * </pre> * This is a short form for the 3x3 matrix: * <pre> * [a, c, tx, * b, d, ty, * 0, 0, 1] * </pre> * The last row is ignored so the array is shorter and operations are faster. */ var mat2d = {}; /** * Creates a new identity mat2d * * @returns {mat2d} a new 2x3 matrix */ mat2d.create = function() { var out = new GLMAT_ARRAY_TYPE(6); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out; }; /** * Creates a new mat2d initialized with values from an existing matrix * * @param {mat2d} a matrix to clone * @returns {mat2d} a new 2x3 matrix */ mat2d.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(6); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; }; /** * Copy the values from one mat2d to another * * @param {mat2d} out the receiving matrix * @param {mat2d} a the source matrix * @returns {mat2d} out */ mat2d.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; }; /** * Set a mat2d to the identity matrix * * @param {mat2d} out the receiving matrix * @returns {mat2d} out */ mat2d.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out; }; /** * Inverts a mat2d * * @param {mat2d} out the receiving matrix * @param {mat2d} a the source matrix * @returns {mat2d} out */ mat2d.invert = function(out, a) { var aa = a[0], ab = a[1], ac = a[2], ad = a[3], atx = a[4], aty = a[5]; var det = aa * ad - ab * ac; if(!det){ return null; } det = 1.0 / det; out[0] = ad * det; out[1] = -ab * det; out[2] = -ac * det; out[3] = aa * det; out[4] = (ac * aty - ad * atx) * det; out[5] = (ab * atx - aa * aty) * det; return out; }; /** * Calculates the determinant of a mat2d * * @param {mat2d} a the source matrix * @returns {Number} determinant of a */ mat2d.determinant = function (a) { return a[0] * a[3] - a[1] * a[2]; }; /** * Multiplies two mat2d's * * @param {mat2d} out the receiving matrix * @param {mat2d} a the first operand * @param {mat2d} b the second operand * @returns {mat2d} out */ mat2d.multiply = function (out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; out[4] = a0 * b4 + a2 * b5 + a4; out[5] = a1 * b4 + a3 * b5 + a5; return out; }; /** * Alias for {@link mat2d.multiply} * @function */ mat2d.mul = mat2d.multiply; /** * Rotates a mat2d by the given angle * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2d} out */ mat2d.rotate = function (out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], s = Math.sin(rad), c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; out[4] = a4; out[5] = a5; return out; }; /** * Scales the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to translate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat2d} out **/ mat2d.scale = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; out[4] = a4; out[5] = a5; return out; }; /** * Translates the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {mat2d} a the matrix to translate * @param {vec2} v the vec2 to translate the matrix by * @returns {mat2d} out **/ mat2d.translate = function(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], v0 = v[0], v1 = v[1]; out[0] = a0; out[1] = a1; out[2] = a2; out[3] = a3; out[4] = a0 * v0 + a2 * v1 + a4; out[5] = a1 * v0 + a3 * v1 + a5; return out; }; /** * Returns a string representation of a mat2d * * @param {mat2d} a matrix to represent as a string * @returns {String} string representation of the matrix */ mat2d.str = function (a) { return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ')'; }; /** * Returns Frobenius norm of a mat2d * * @param {mat2d} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat2d.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1)) }; if(typeof(exports) !== 'undefined') { exports.mat2d = mat2d; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 3x3 Matrix * @name mat3 */ var mat3 = {}; /** * Creates a new identity mat3 * * @returns {mat3} a new 3x3 matrix */ mat3.create = function() { var out = new GLMAT_ARRAY_TYPE(9); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 1; out[5] = 0; out[6] = 0; out[7] = 0; out[8] = 1; return out; }; /** * Copies the upper-left 3x3 values into the given mat3. * * @param {mat3} out the receiving 3x3 matrix * @param {mat4} a the source 4x4 matrix * @returns {mat3} out */ mat3.fromMat4 = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[4]; out[4] = a[5]; out[5] = a[6]; out[6] = a[8]; out[7] = a[9]; out[8] = a[10]; return out; }; /** * Creates a new mat3 initialized with values from an existing matrix * * @param {mat3} a matrix to clone * @returns {mat3} a new 3x3 matrix */ mat3.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(9); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Copy the values from one mat3 to another * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Set a mat3 to the identity matrix * * @param {mat3} out the receiving matrix * @returns {mat3} out */ mat3.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 1; out[5] = 0; out[6] = 0; out[7] = 0; out[8] = 1; return out; }; /** * Transpose the values of a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a01 = a[1], a02 = a[2], a12 = a[5]; out[1] = a[3]; out[2] = a[6]; out[3] = a01; out[5] = a[7]; out[6] = a02; out[7] = a12; } else { out[0] = a[0]; out[1] = a[3]; out[2] = a[6]; out[3] = a[1]; out[4] = a[4]; out[5] = a[7]; out[6] = a[2]; out[7] = a[5]; out[8] = a[8]; } return out; }; /** * Inverts a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.invert = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], b01 = a22 * a11 - a12 * a21, b11 = -a22 * a10 + a12 * a20, b21 = a21 * a10 - a11 * a20, // Calculate the determinant det = a00 * b01 + a01 * b11 + a02 * b21; if (!det) { return null; } det = 1.0 / det; out[0] = b01 * det; out[1] = (-a22 * a01 + a02 * a21) * det; out[2] = (a12 * a01 - a02 * a11) * det; out[3] = b11 * det; out[4] = (a22 * a00 - a02 * a20) * det; out[5] = (-a12 * a00 + a02 * a10) * det; out[6] = b21 * det; out[7] = (-a21 * a00 + a01 * a20) * det; out[8] = (a11 * a00 - a01 * a10) * det; return out; }; /** * Calculates the adjugate of a mat3 * * @param {mat3} out the receiving matrix * @param {mat3} a the source matrix * @returns {mat3} out */ mat3.adjoint = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8]; out[0] = (a11 * a22 - a12 * a21); out[1] = (a02 * a21 - a01 * a22); out[2] = (a01 * a12 - a02 * a11); out[3] = (a12 * a20 - a10 * a22); out[4] = (a00 * a22 - a02 * a20); out[5] = (a02 * a10 - a00 * a12); out[6] = (a10 * a21 - a11 * a20); out[7] = (a01 * a20 - a00 * a21); out[8] = (a00 * a11 - a01 * a10); return out; }; /** * Calculates the determinant of a mat3 * * @param {mat3} a the source matrix * @returns {Number} determinant of a */ mat3.determinant = function (a) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8]; return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); }; /** * Multiplies two mat3's * * @param {mat3} out the receiving matrix * @param {mat3} a the first operand * @param {mat3} b the second operand * @returns {mat3} out */ mat3.multiply = function (out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], b00 = b[0], b01 = b[1], b02 = b[2], b10 = b[3], b11 = b[4], b12 = b[5], b20 = b[6], b21 = b[7], b22 = b[8]; out[0] = b00 * a00 + b01 * a10 + b02 * a20; out[1] = b00 * a01 + b01 * a11 + b02 * a21; out[2] = b00 * a02 + b01 * a12 + b02 * a22; out[3] = b10 * a00 + b11 * a10 + b12 * a20; out[4] = b10 * a01 + b11 * a11 + b12 * a21; out[5] = b10 * a02 + b11 * a12 + b12 * a22; out[6] = b20 * a00 + b21 * a10 + b22 * a20; out[7] = b20 * a01 + b21 * a11 + b22 * a21; out[8] = b20 * a02 + b21 * a12 + b22 * a22; return out; }; /** * Alias for {@link mat3.multiply} * @function */ mat3.mul = mat3.multiply; /** * Translate a mat3 by the given vector * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to translate * @param {vec2} v vector to translate by * @returns {mat3} out */ mat3.translate = function(out, a, v) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], x = v[0], y = v[1]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a10; out[4] = a11; out[5] = a12; out[6] = x * a00 + y * a10 + a20; out[7] = x * a01 + y * a11 + a21; out[8] = x * a02 + y * a12 + a22; return out; }; /** * Rotates a mat3 by the given angle * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat3} out */ mat3.rotate = function (out, a, rad) { var a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8], s = Math.sin(rad), c = Math.cos(rad); out[0] = c * a00 + s * a10; out[1] = c * a01 + s * a11; out[2] = c * a02 + s * a12; out[3] = c * a10 - s * a00; out[4] = c * a11 - s * a01; out[5] = c * a12 - s * a02; out[6] = a20; out[7] = a21; out[8] = a22; return out; }; /** * Scales the mat3 by the dimensions in the given vec2 * * @param {mat3} out the receiving matrix * @param {mat3} a the matrix to rotate * @param {vec2} v the vec2 to scale the matrix by * @returns {mat3} out **/ mat3.scale = function(out, a, v) { var x = v[0], y = v[1]; out[0] = x * a[0]; out[1] = x * a[1]; out[2] = x * a[2]; out[3] = y * a[3]; out[4] = y * a[4]; out[5] = y * a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; return out; }; /** * Copies the values from a mat2d into a mat3 * * @param {mat3} out the receiving matrix * @param {mat2d} a the matrix to copy * @returns {mat3} out **/ mat3.fromMat2d = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = 0; out[3] = a[2]; out[4] = a[3]; out[5] = 0; out[6] = a[4]; out[7] = a[5]; out[8] = 1; return out; }; /** * Calculates a 3x3 matrix from the given quaternion * * @param {mat3} out mat3 receiving operation result * @param {quat} q Quaternion to create matrix from * * @returns {mat3} out */ mat3.fromQuat = function (out, q) { var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - yy - zz; out[3] = yx - wz; out[6] = zx + wy; out[1] = yx + wz; out[4] = 1 - xx - zz; out[7] = zy - wx; out[2] = zx - wy; out[5] = zy + wx; out[8] = 1 - xx - yy; return out; }; /** * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix * * @param {mat3} out mat3 receiving operation result * @param {mat4} a Mat4 to derive the normal matrix from * * @returns {mat3} out */ mat3.normalFromMat4 = function (out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, // Calculate the determinant det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det; return out; }; /** * Returns a string representation of a mat3 * * @param {mat3} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat3.str = function (a) { return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')'; }; /** * Returns Frobenius norm of a mat3 * * @param {mat3} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat3.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2))) }; if(typeof(exports) !== 'undefined') { exports.mat3 = mat3; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class 4x4 Matrix * @name mat4 */ var mat4 = {}; /** * Creates a new identity mat4 * * @returns {mat4} a new 4x4 matrix */ mat4.create = function() { var out = new GLMAT_ARRAY_TYPE(16); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Creates a new mat4 initialized with values from an existing matrix * * @param {mat4} a matrix to clone * @returns {mat4} a new 4x4 matrix */ mat4.clone = function(a) { var out = new GLMAT_ARRAY_TYPE(16); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Copy the values from one mat4 to another * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.copy = function(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Set a mat4 to the identity matrix * * @param {mat4} out the receiving matrix * @returns {mat4} out */ mat4.identity = function(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Transpose the values of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.transpose = function(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a01 = a[1], a02 = a[2], a03 = a[3], a12 = a[6], a13 = a[7], a23 = a[11]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a01; out[6] = a[9]; out[7] = a[13]; out[8] = a02; out[9] = a12; out[11] = a[14]; out[12] = a03; out[13] = a13; out[14] = a23; } else { out[0] = a[0]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a[1]; out[5] = a[5]; out[6] = a[9]; out[7] = a[13]; out[8] = a[2]; out[9] = a[6]; out[10] = a[10]; out[11] = a[14]; out[12] = a[3]; out[13] = a[7]; out[14] = a[11]; out[15] = a[15]; } return out; }; /** * Inverts a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.invert = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, // Calculate the determinant det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; }; /** * Calculates the adjugate of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ mat4.adjoint = function(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); return out; }; /** * Calculates the determinant of a mat4 * * @param {mat4} a the source matrix * @returns {Number} determinant of a */ mat4.determinant = function (a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32; // Calculate the determinant return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; }; /** * Multiplies two mat4's * * @param {mat4} out the receiving matrix * @param {mat4} a the first operand * @param {mat4} b the second operand * @returns {mat4} out */ mat4.multiply = function (out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; // Cache only the current line of the second matrix var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; return out; }; /** * Alias for {@link mat4.multiply} * @function */ mat4.mul = mat4.multiply; /** * Translate a mat4 by the given vector * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to translate * @param {vec3} v vector to translate by * @returns {mat4} out */ mat4.translate = function (out, a, v) { var x = v[0], y = v[1], z = v[2], a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23; if (a === out) { out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; } else { a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; out[12] = a00 * x + a10 * y + a20 * z + a[12]; out[13] = a01 * x + a11 * y + a21 * z + a[13]; out[14] = a02 * x + a12 * y + a22 * z + a[14]; out[15] = a03 * x + a13 * y + a23 * z + a[15]; } return out; }; /** * Scales the mat4 by the dimensions in the given vec3 * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to scale * @param {vec3} v the vec3 to scale the matrix by * @returns {mat4} out **/ mat4.scale = function(out, a, v) { var x = v[0], y = v[1], z = v[2]; out[0] = a[0] * x; out[1] = a[1] * x; out[2] = a[2] * x; out[3] = a[3] * x; out[4] = a[4] * y; out[5] = a[5] * y; out[6] = a[6] * y; out[7] = a[7] * y; out[8] = a[8] * z; out[9] = a[9] * z; out[10] = a[10] * z; out[11] = a[11] * z; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; /** * Rotates a mat4 by the given angle * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @param {vec3} axis the axis to rotate around * @returns {mat4} out */ mat4.rotate = function (out, a, rad, axis) { var x = axis[0], y = axis[1], z = axis[2], len = Math.sqrt(x * x + y * y + z * z), s, c, t, a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20, b21, b22; if (Math.abs(len) < GLMAT_EPSILON) { return null; } len = 1 / len; x *= len; y *= len; z *= len; s = Math.sin(rad); c = Math.cos(rad); t = 1 - c; a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; // Construct the elements of the rotation matrix b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; // Perform rotation-specific matrix multiplication out[0] = a00 * b00 + a10 * b01 + a20 * b02; out[1] = a01 * b00 + a11 * b01 + a21 * b02; out[2] = a02 * b00 + a12 * b01 + a22 * b02; out[3] = a03 * b00 + a13 * b01 + a23 * b02; out[4] = a00 * b10 + a10 * b11 + a20 * b12; out[5] = a01 * b10 + a11 * b11 + a21 * b12; out[6] = a02 * b10 + a12 * b11 + a22 * b12; out[7] = a03 * b10 + a13 * b11 + a23 * b12; out[8] = a00 * b20 + a10 * b21 + a20 * b22; out[9] = a01 * b20 + a11 * b21 + a21 * b22; out[10] = a02 * b20 + a12 * b21 + a22 * b22; out[11] = a03 * b20 + a13 * b21 + a23 * b22; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } return out; }; /** * Rotates a matrix by the given angle around the X axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateX = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[4] = a10 * c + a20 * s; out[5] = a11 * c + a21 * s; out[6] = a12 * c + a22 * s; out[7] = a13 * c + a23 * s; out[8] = a20 * c - a10 * s; out[9] = a21 * c - a11 * s; out[10] = a22 * c - a12 * s; out[11] = a23 * c - a13 * s; return out; }; /** * Rotates a matrix by the given angle around the Y axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateY = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c - a20 * s; out[1] = a01 * c - a21 * s; out[2] = a02 * c - a22 * s; out[3] = a03 * c - a23 * s; out[8] = a00 * s + a20 * c; out[9] = a01 * s + a21 * c; out[10] = a02 * s + a22 * c; out[11] = a03 * s + a23 * c; return out; }; /** * Rotates a matrix by the given angle around the Z axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ mat4.rotateZ = function (out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c + a10 * s; out[1] = a01 * c + a11 * s; out[2] = a02 * c + a12 * s; out[3] = a03 * c + a13 * s; out[4] = a10 * c - a00 * s; out[5] = a11 * c - a01 * s; out[6] = a12 * c - a02 * s; out[7] = a13 * c - a03 * s; return out; }; /** * Creates a matrix from a quaternion rotation and vector translation * This is equivalent to (but much faster than): * * mat4.identity(dest); * mat4.translate(dest, vec); * var quatMat = mat4.create(); * quat4.toMat4(quat, quatMat); * mat4.multiply(dest, quatMat); * * @param {mat4} out mat4 receiving operation result * @param {quat4} q Rotation quaternion * @param {vec3} v Translation vector * @returns {mat4} out */ mat4.fromRotationTranslation = function (out, q, v) { // Quaternion math var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - (yy + zz); out[1] = xy + wz; out[2] = xz - wy; out[3] = 0; out[4] = xy - wz; out[5] = 1 - (xx + zz); out[6] = yz + wx; out[7] = 0; out[8] = xz + wy; out[9] = yz - wx; out[10] = 1 - (xx + yy); out[11] = 0; out[12] = v[0]; out[13] = v[1]; out[14] = v[2]; out[15] = 1; return out; }; mat4.fromQuat = function (out, q) { var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - yy - zz; out[1] = yx + wz; out[2] = zx - wy; out[3] = 0; out[4] = yx - wz; out[5] = 1 - xx - zz; out[6] = zy + wx; out[7] = 0; out[8] = zx + wy; out[9] = zy - wx; out[10] = 1 - xx - yy; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; /** * Generates a frustum matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {Number} left Left bound of the frustum * @param {Number} right Right bound of the frustum * @param {Number} bottom Bottom bound of the frustum * @param {Number} top Top bound of the frustum * @param {Number} near Near bound of the frustum * @param {Number} far Far bound of the frustum * @returns {mat4} out */ mat4.frustum = function (out, left, right, bottom, top, near, far) { var rl = 1 / (right - left), tb = 1 / (top - bottom), nf = 1 / (near - far); out[0] = (near * 2) * rl; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = (near * 2) * tb; out[6] = 0; out[7] = 0; out[8] = (right + left) * rl; out[9] = (top + bottom) * tb; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (far * near * 2) * nf; out[15] = 0; return out; }; /** * Generates a perspective projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} fovy Vertical field of view in radians * @param {number} aspect Aspect ratio. typically viewport width/height * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ mat4.perspective = function (out, fovy, aspect, near, far) { var f = 1.0 / Math.tan(fovy / 2), nf = 1 / (near - far); out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (2 * far * near) * nf; out[15] = 0; return out; }; /** * Generates a orthogonal projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} left Left bound of the frustum * @param {number} right Right bound of the frustum * @param {number} bottom Bottom bound of the frustum * @param {number} top Top bound of the frustum * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ mat4.ortho = function (out, left, right, bottom, top, near, far) { var lr = 1 / (left - right), bt = 1 / (bottom - top), nf = 1 / (near - far); out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 2 * nf; out[11] = 0; out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1; return out; }; /** * Generates a look-at matrix with the given eye position, focal point, and up axis * * @param {mat4} out mat4 frustum matrix will be written into * @param {vec3} eye Position of the viewer * @param {vec3} center Point the viewer is looking at * @param {vec3} up vec3 pointing up * @returns {mat4} out */ mat4.lookAt = function (out, eye, center, up) { var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, eyex = eye[0], eyey = eye[1], eyez = eye[2], upx = up[0], upy = up[1], upz = up[2], centerx = center[0], centery = center[1], centerz = center[2]; if (Math.abs(eyex - centerx) < GLMAT_EPSILON && Math.abs(eyey - centery) < GLMAT_EPSILON && Math.abs(eyez - centerz) < GLMAT_EPSILON) { return mat4.identity(out); } z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz; len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len; z1 *= len; z2 *= len; x0 = upy * z2 - upz * z1; x1 = upz * z0 - upx * z2; x2 = upx * z1 - upy * z0; len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (!len) { x0 = 0; x1 = 0; x2 = 0; } else { len = 1 / len; x0 *= len; x1 *= len; x2 *= len; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (!len) { y0 = 0; y1 = 0; y2 = 0; } else { len = 1 / len; y0 *= len; y1 *= len; y2 *= len; } out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0; out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0; out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0; out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); out[15] = 1; return out; }; /** * Returns a string representation of a mat4 * * @param {mat4} mat matrix to represent as a string * @returns {String} string representation of the matrix */ mat4.str = function (a) { return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; }; /** * Returns Frobenius norm of a mat4 * * @param {mat4} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ mat4.frob = function (a) { return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) )) }; if(typeof(exports) !== 'undefined') { exports.mat4 = mat4; } ; /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @class Quaternion * @name quat */ var quat = {}; /** * Creates a new identity quat * * @returns {quat} a new quaternion */ quat.create = function() { var out = new GLMAT_ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Sets a quaternion to represent the shortest rotation from one * vector to another. * * Both vectors are assumed to be unit length. * * @param {quat} out the receiving quaternion. * @param {vec3} a the initial vector * @param {vec3} b the destination vector * @returns {quat} out */ quat.rotationTo = (function() { var tmpvec3 = vec3.create(); var xUnitVec3 = vec3.fromValues(1,0,0); var yUnitVec3 = vec3.fromValues(0,1,0); return function(out, a, b) { var dot = vec3.dot(a, b); if (dot < -0.999999) { vec3.cross(tmpvec3, xUnitVec3, a); if (vec3.length(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a); vec3.normalize(tmpvec3, tmpvec3); quat.setAxisAngle(out, tmpvec3, Math.PI); return out; } else if (dot > 0.999999) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } else { vec3.cross(tmpvec3, a, b); out[0] = tmpvec3[0]; out[1] = tmpvec3[1]; out[2] = tmpvec3[2]; out[3] = 1 + dot; return quat.normalize(out, out); } }; })(); /** * Sets the specified quaternion with values corresponding to the given * axes. Each axis is a vec3 and is expected to be unit length and * perpendicular to all other specified axes. * * @param {vec3} view the vector representing the viewing direction * @param {vec3} right the vector representing the local "right" direction * @param {vec3} up the vector representing the local "up" direction * @returns {quat} out */ quat.setAxes = (function() { var matr = mat3.create(); return function(out, view, right, up) { matr[0] = right[0]; matr[3] = right[1]; matr[6] = right[2]; matr[1] = up[0]; matr[4] = up[1]; matr[7] = up[2]; matr[2] = -view[0]; matr[5] = -view[1]; matr[8] = -view[2]; return quat.normalize(out, quat.fromMat3(out, matr)); }; })(); /** * Creates a new quat initialized with values from an existing quaternion * * @param {quat} a quaternion to clone * @returns {quat} a new quaternion * @function */ quat.clone = vec4.clone; /** * Creates a new quat initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {quat} a new quaternion * @function */ quat.fromValues = vec4.fromValues; /** * Copy the values from one quat to another * * @param {quat} out the receiving quaternion * @param {quat} a the source quaternion * @returns {quat} out * @function */ quat.copy = vec4.copy; /** * Set the components of a quat to the given values * * @param {quat} out the receiving quaternion * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {quat} out * @function */ quat.set = vec4.set; /** * Set a quat to the identity quaternion * * @param {quat} out the receiving quaternion * @returns {quat} out */ quat.identity = function(out) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; }; /** * Sets a quat from the given angle and rotation axis, * then returns it. * * @param {quat} out the receiving quaternion * @param {vec3} axis the axis around which to rotate * @param {Number} rad the angle in radians * @returns {quat} out **/ quat.setAxisAngle = function(out, axis, rad) { rad = rad * 0.5; var s = Math.sin(rad); out[0] = s * axis[0]; out[1] = s * axis[1]; out[2] = s * axis[2]; out[3] = Math.cos(rad); return out; }; /** * Adds two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @returns {quat} out * @function */ quat.add = vec4.add; /** * Multiplies two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @returns {quat} out */ quat.multiply = function(out, a, b) { var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3]; out[0] = ax * bw + aw * bx + ay * bz - az * by; out[1] = ay * bw + aw * by + az * bx - ax * bz; out[2] = az * bw + aw * bz + ax * by - ay * bx; out[3] = aw * bw - ax * bx - ay * by - az * bz; return out; }; /** * Alias for {@link quat.multiply} * @function */ quat.mul = quat.multiply; /** * Scales a quat by a scalar number * * @param {quat} out the receiving vector * @param {quat} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {quat} out * @function */ quat.scale = vec4.scale; /** * Rotates a quaternion by the given angle about the X axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateX = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw + aw * bx; out[1] = ay * bw + az * bx; out[2] = az * bw - ay * bx; out[3] = aw * bw - ax * bx; return out; }; /** * Rotates a quaternion by the given angle about the Y axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateY = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], by = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw - az * by; out[1] = ay * bw + aw * by; out[2] = az * bw + ax * by; out[3] = aw * bw - ay * by; return out; }; /** * Rotates a quaternion by the given angle about the Z axis * * @param {quat} out quat receiving operation result * @param {quat} a quat to rotate * @param {number} rad angle (in radians) to rotate * @returns {quat} out */ quat.rotateZ = function (out, a, rad) { rad *= 0.5; var ax = a[0], ay = a[1], az = a[2], aw = a[3], bz = Math.sin(rad), bw = Math.cos(rad); out[0] = ax * bw + ay * bz; out[1] = ay * bw - ax * bz; out[2] = az * bw + aw * bz; out[3] = aw * bw - az * bz; return out; }; /** * Calculates the W component of a quat from the X, Y, and Z components. * Assumes that quaternion is 1 unit in length. * Any existing W component will be ignored. * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate W component of * @returns {quat} out */ quat.calculateW = function (out, a) { var x = a[0], y = a[1], z = a[2]; out[0] = x; out[1] = y; out[2] = z; out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); return out; }; /** * Calculates the dot product of two quat's * * @param {quat} a the first operand * @param {quat} b the second operand * @returns {Number} dot product of a and b * @function */ quat.dot = vec4.dot; /** * Performs a linear interpolation between two quat's * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {quat} out * @function */ quat.lerp = vec4.lerp; /** * Performs a spherical linear interpolation between two quat * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {quat} out */ quat.slerp = function (out, a, b, t) { // benchmarks: // http://jsperf.com/quaternion-slerp-implementations var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3]; var omega, cosom, sinom, scale0, scale1; // calc cosine cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary) if ( cosom < 0.0 ) { cosom = -cosom; bx = - bx; by = - by; bz = - bz; bw = - bw; } // calculate coefficients if ( (1.0 - cosom) > 0.000001 ) { // standard case (slerp) omega = Math.acos(cosom); sinom = Math.sin(omega); scale0 = Math.sin((1.0 - t) * omega) / sinom; scale1 = Math.sin(t * omega) / sinom; } else { // "from" and "to" quaternions are very close // ... so we can do a linear interpolation scale0 = 1.0 - t; scale1 = t; } // calculate final values out[0] = scale0 * ax + scale1 * bx; out[1] = scale0 * ay + scale1 * by; out[2] = scale0 * az + scale1 * bz; out[3] = scale0 * aw + scale1 * bw; return out; }; /** * Calculates the inverse of a quat * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate inverse of * @returns {quat} out */ quat.invert = function(out, a) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, invDot = dot ? 1.0/dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 out[0] = -a0*invDot; out[1] = -a1*invDot; out[2] = -a2*invDot; out[3] = a3*invDot; return out; }; /** * Calculates the conjugate of a quat * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. * * @param {quat} out the receiving quaternion * @param {quat} a quat to calculate conjugate of * @returns {quat} out */ quat.conjugate = function (out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a[3]; return out; }; /** * Calculates the length of a quat * * @param {quat} a vector to calculate length of * @returns {Number} length of a * @function */ quat.length = vec4.length; /** * Alias for {@link quat.length} * @function */ quat.len = quat.length; /** * Calculates the squared length of a quat * * @param {quat} a vector to calculate squared length of * @returns {Number} squared length of a * @function */ quat.squaredLength = vec4.squaredLength; /** * Alias for {@link quat.squaredLength} * @function */ quat.sqrLen = quat.squaredLength; /** * Normalize a quat * * @param {quat} out the receiving quaternion * @param {quat} a quaternion to normalize * @returns {quat} out * @function */ quat.normalize = vec4.normalize; /** * Creates a quaternion from the given 3x3 rotation matrix. * * NOTE: The resultant quaternion is not normalized, so you should be sure * to renormalize the quaternion yourself where necessary. * * @param {quat} out the receiving quaternion * @param {mat3} m rotation matrix * @returns {quat} out * @function */ quat.fromMat3 = function(out, m) { // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes // article "Quaternion Calculus and Fast Animation". var fTrace = m[0] + m[4] + m[8]; var fRoot; if ( fTrace > 0.0 ) { // |w| > 1/2, may as well choose w > 1/2 fRoot = Math.sqrt(fTrace + 1.0); // 2w out[3] = 0.5 * fRoot; fRoot = 0.5/fRoot; // 1/(4w) out[0] = (m[7]-m[5])*fRoot; out[1] = (m[2]-m[6])*fRoot; out[2] = (m[3]-m[1])*fRoot; } else { // |w| <= 1/2 var i = 0; if ( m[4] > m[0] ) i = 1; if ( m[8] > m[i*3+i] ) i = 2; var j = (i+1)%3; var k = (i+2)%3; fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); out[i] = 0.5 * fRoot; fRoot = 0.5 / fRoot; out[3] = (m[k*3+j] - m[j*3+k]) * fRoot; out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; } return out; }; /** * Returns a string representation of a quatenion * * @param {quat} vec vector to represent as a string * @returns {String} string representation of the vector */ quat.str = function (a) { return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; }; if(typeof(exports) !== 'undefined') { exports.quat = quat; } ; })(shim.exports); })(this); },{}],105:[function(require,module,exports){ 'use strict'; function constant(value) { return function() { return value; } } function interpolateNumber(a, b, t) { return (a * (1 - t)) + (b * t); } function interpolateArray(a, b, t) { var result = []; for (var i = 0; i < a.length; i++) { result[i] = interpolateNumber(a[i], b[i], t); } return result; } exports['interpolated'] = function(f) { if (!f.stops) { return constant(f); } var stops = f.stops, base = f.base || 1, interpolate = Array.isArray(stops[0][1]) ? interpolateArray : interpolateNumber; return function(z) { // find the two stops which the current z is between var low, high; for (var i = 0; i < stops.length; i++) { var stop = stops[i]; if (stop[0] <= z) { low = stop; } if (stop[0] > z) { high = stop; break; } } if (low && high) { var zoomDiff = high[0] - low[0], zoomProgress = z - low[0], t = base === 1 ? zoomProgress / zoomDiff : (Math.pow(base, zoomProgress) - 1) / (Math.pow(base, zoomDiff) - 1); return interpolate(low[1], high[1], t); } else if (low) { return low[1]; } else if (high) { return high[1]; } }; }; exports['piecewise-constant'] = function(f) { if (!f.stops) { return constant(f); } var stops = f.stops; return function(z) { for (var i = 0; i < stops.length; i++) { if (stops[i][0] > z) { return stops[i === 0 ? 0 : i - 1][1]; } } return stops[stops.length - 1][1]; } }; },{}],106:[function(require,module,exports){ 'use strict'; var reference = require('../../reference/latest.js'); var validate = require('./parsed'); module.exports = function(style) { return validate(style, reference); }; },{"../../reference/latest.js":108,"./parsed":107}],107:[function(require,module,exports){ 'use strict'; var parseCSSColor = require('csscolorparser').parseCSSColor; var format = require('util').format; module.exports = function(style, reference) { var constants = style.constants || {}, layers = {}, errors = []; function error(key, val /*, message, ...*/) { var err = { message: (key ? key + ': ' : '') + format.apply(format, Array.prototype.slice.call(arguments, 2)) }; if (val !== null && val !== undefined && val.__line__) { err.line = val.__line__; } errors.push(err); } // Main recursive validation function. Tracks: // // - key: string representing location of validation in style tree. Used only // for more informative error reporting. // - val: current value from style being evaluated. May be anything from a // high level object that needs to be descended into deeper or a simple // scalar value. // - spec: current spec being evaluated. Tracks val. // function validate(key, val, spec) { var type = typeof_(val); // Constants if (type === 'string' && val[0] === '@') { if (!(val in constants)) { return error(key, val, 'constant "%s" not found', val); } val = constants[val]; type = typeof_(val); } // Functions if (spec.function && type === 'object') { return validate.function(key, val, spec); } if (spec.type) { var validator = validate[spec.type]; if (validator) { return validator(key, val, spec); } spec = reference[spec.type]; } validate.object(key, val, spec); } validate.constants = function(key, val) { var type = typeof_(val); if (type !== 'object') { return error(key, val, 'object expected, %s found', type); } for (var k in val) { if (k[0] !== '@') { error(key + '.' + k, val[k], 'constants must start with "@"'); } } }; validate.source = function(key, val) { if (!val.type) { error(key, val, '"type" is required'); return; } var type = unbundle(val.type); switch (type) { case 'vector': case 'raster': validate.object(key, val, reference.source_tile); if ('url' in val) { for (var prop in val) { if (['type', 'url', 'tileSize'].indexOf(prop) < 0) { error(key + '.' + prop, val[prop], 'a source with a "url" property may not include a "%s" property', prop); } } } break; case 'geojson': validate.object(key, val, reference.source_geojson); break; case 'video': validate.object(key, val, reference.source_video); break; default: validate.enum(key + '.type', val.type, {values: ['vector', 'raster', 'geojson', 'video']}); } }; validate.layer = function(key, val) { if (!val.type && !val.ref) { error(key, val, 'either "type" or "ref" is required'); } var type = unbundle(val.type), ref = unbundle(val.ref); if (val.id) { if (layers[val.id]) { error(key, val.id, 'duplicate layer id "%s", previously used at line %d', val.id, layers[val.id]); } else { layers[val.id] = val.id.__line__; } } if ('ref' in val) { ['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) { if (p in val) { error(key, val[p], '"%s" is prohibited for ref layers', p); } }); var parent; style.layers.forEach(function(layer) { if (layer.id == ref) parent = layer; }); if (!parent) { error(key, val.ref, 'ref layer "%s" not found', ref); } else if (parent.ref) { error(key, val.ref, 'ref cannot reference another ref layer'); } else { type = parent.type; } } else if (type !== 'background') { if (!val.source) { error(key, val, 'missing required property "source"'); } else { var source = style.sources[val.source]; if (!source) { error(key, val.source, 'source "%s" not found', val.source); } else if (source.type == 'vector' && type == 'raster') { error(key, val.source, 'layer "%s" requires a raster source', val.id); } else if (source.type == 'raster' && type != 'raster') { error(key, val.source, 'layer "%s" requires a vector source', val.id); } } } validate.object(key, val, reference.layer, { filter: validate.filter, layout: function(key, val) { var spec = reference['layout_' + type]; return type && spec && validate(key, val, spec); }, paint: function(key, val) { var spec = reference['paint_' + type]; return type && spec && validate(key, val, spec); } }); }; validate.object = function (key, val, spec, validators) { validators = validators || {}; var type = typeof_(val); if (type !== 'object') { return error(key, val, 'object expected, %s found', type); } for (var k in val) { var speckey = k.split('.')[0]; // treat 'paint.*' as 'paint' var def = spec[speckey] || spec['*']; var transition = speckey.match(/^(.*)-transition$/); if (def) { (validators[speckey] || validate)((key ? key + '.' : key) + k, val[k], def); } else if (transition && spec[transition[1]] && spec[transition[1]].transition) { validate((key ? key + '.' : key) + k, val[k], reference.transition); // tolerate root-level extra keys & arbitrary layer properties } else if (key !== '' && key.split('.').length !== 1) { error(key, val[k], 'unknown property "%s"', k); } } for (var l in spec) { if (spec[l].required && spec[l]['default'] === undefined && val[l] === undefined) { error(key, val, 'missing required property "%s"', l); } } }; validate.array = function (key, val, spec, validator) { if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (spec.length && val.length !== spec.length) { return error(key, val, 'array length %d expected, length %d found', spec.length, val.length); } var value = { "type": spec.value }; if (style.version < 7) { value.function = spec.function; } if (typeof_(spec.value) === 'object') { value = spec.value; } for (var i = 0; i < val.length; i++) { (validator || validate)(key + '[' + i + ']', val[i], value); } }; validate.filter = function(key, val) { var type; if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (val.length < 1) { return error(key, val, 'filter array must have at least 1 element'); } validate.enum(key + '[0]', val[0], reference.filter_operator); switch (unbundle(val[0])) { case '<': case '<=': case '>': case '>=': if (val.length >= 2 && val[1] == '$type') { error(key, val, '"$type" cannot be use with operator "%s"', val[0]); } /* falls through */ case '==': case '!=': if (val.length != 3) { error(key, val, 'filter array for operator "%s" must have 3 elements', val[0]); } /* falls through */ case 'in': case '!in': if (val.length >= 2) { type = typeof_(val[1]); if (type !== 'string') { error(key + '[1]', val[1], 'string expected, %s found', type); } else if (val[1][0] === '@') { error(key + '[1]', val[1], 'filter key cannot be a constant'); } } for (var i = 2; i < val.length; i++) { type = typeof_(val[i]); if (val[1] == '$type') { validate.enum(key + '[' + i + ']', val[i], reference.geometry_type); } else if (type === 'string' && val[i][0] === '@') { error(key + '[' + i + ']', val[i], 'filter value cannot be a constant'); } else if (type !== 'string' && type !== 'number' && type !== 'boolean') { error(key + '[' + i + ']', val[i], 'string, number, or boolean expected, %s found', type); } } break; case 'any': case 'all': case 'none': for (i = 1; i < val.length; i++) { validate.filter(key + '[' + i + ']', val[i]); } break; } }; validate.function = function(key, val, spec) { validate.object(key, val, reference.function, { stops: function (key, val, arraySpec) { var lastStop = -Infinity; validate.array(key, val, arraySpec, function validateStop(key, val) { if (typeof_(val) !== 'array') { return error(key, val, 'array expected, %s found', typeof_(val)); } if (val.length !== 2) { return error(key, val, 'array length %d expected, length %d found', 2, val.length); } validate(key + '[0]', val[0], {type: 'number'}); validate(key + '[1]', val[1], spec); if (typeof_(val[0]) === 'number') { if (spec.function === 'piecewise-constant' && val[0] % 1 !== 0) { error(key + '[0]', val[0], 'zoom level for piecewise-constant functions must be an integer'); } if (val[0] < lastStop) { error(key + '[0]', val[0], 'array stops must appear in ascending order'); } lastStop = val[0]; } }); if (typeof_(val) === 'array' && val.length === 0) { error(key, val, 'array must have at least one stop'); } } }); }; validate.enum = function (key, val, spec) { if (spec.values.indexOf(unbundle(val)) === -1) { error(key, val, 'expected one of [%s], %s found', spec.values.join(', '), val); } }; validate.color = function(key, val) { var type = typeof_(val); if (type !== 'string') { error(key, val, 'color expected, %s found', type); } else if (parseCSSColor(val) === null) { error(key, val, 'color expected, "%s" found', val); } }; function typeValidator(expected) { return function(key, val, spec) { var actual = typeof_(val); if (actual !== expected) { error(key, val, '%s expected, %s found', expected, actual); } if ('minimum' in spec && val < spec.minimum) { error(key, val, '%s is less than the minimum value %s', val, spec.minimum); } if ('maximum' in spec && val > spec.maximum) { error(key, val, '%s is greater than the maximum value %s', val, spec.maximum); } }; } validate.number = typeValidator('number'); validate.string = typeValidator('string'); validate.boolean = typeValidator('boolean'); validate['*'] = function() {}; validate('', style, reference.$root); return errors; }; function typeof_(val) { if (val instanceof Number) return 'number'; if (val instanceof String) return 'string'; if (val instanceof Boolean) return 'boolean'; if (Array.isArray(val)) return 'array'; if (val === null) return 'null'; return typeof val; } function unbundle(_) { if (_ instanceof Number || _ instanceof String || _ instanceof Boolean) { return _.valueOf(); } else { return _; } } },{"csscolorparser":97,"util":124}],108:[function(require,module,exports){ module.exports = require('./v7.json'); },{"./v7.json":109}],109:[function(require,module,exports){ module.exports={ "$version": 7, "$root": { "version": { "required": true, "type": "enum", "values": [ 7 ], "doc": "Stylesheet version number. Must be 7." }, "name": { "type": "string", "doc": "A human-readable name for the style." }, "constants": { "type": "constants", "doc": "An object of constants to be referenced in layers." }, "sources": { "required": true, "type": "sources", "doc": "Data source specifications." }, "sprite": { "type": "string", "doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended." }, "glyphs": { "type": "string", "doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}." }, "transition": { "type": "transition", "doc": "A global transition definition to use as a default across properties." }, "layers": { "required": true, "type": "array", "value": "layer", "doc": "Layers will be drawn in the order of this array." } }, "constants": { "*": { "type": "*", "doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol." } }, "sources": { "*": { "type": "source", "doc": "Specification of a data source. For vector and raster sources, either TileJSON or a URL to a TileJSON must be provided. For GeoJSON and video sources, a URL must be provided." } }, "source": [ "source_tile", "source_geojson", "source_video" ], "source_tile": { "type": { "required": true, "type": "enum", "values": [ "vector", "raster" ], "doc": "The data type of the source." }, "url": { "type": "string", "doc": "A URL to a TileJSON resource. Supported protocols are `http:`, `https:`, and `mapbox://<mapid>`." }, "tiles": { "type": "array", "value": "string", "doc": "An array of one or more tile source URLs, as in the TileJSON spec." }, "minzoom": { "type": "number", "default": 0, "doc": "Minimum zoom level for which tiles are available, as in the TileJSON spec." }, "maxzoom": { "type": "number", "default": 22, "doc": "Maximum zoom level for which tiles are available, as in the TileJSON spec. Data from tiles at the maxzoom are used when displaying the map at higher zoom levels." }, "tileSize": { "type": "number", "default": 512, "units": "pixels", "doc": "The minimum visual size to display tiles for this layer. Only configurable for raster layers." }, "*": { "type": "*", "doc": "Other keys to configure the data source." } }, "source_geojson": { "type": { "required": true, "type": "enum", "values": [ "geojson" ] }, "data": { "type": "*" } }, "source_video": { "type": { "required": true, "type": "enum", "values": [ "video" ] }, "url": { "required": true, "type": "array", "value": "string", "doc": "URLs to video content in order of preferred format." }, "coordinates": { "required": true, "type": "array", "length": 4, "value": { "type": "array", "length": 2, "value": "number" } } }, "layer": { "id": { "type": "string", "doc": "Unique layer name." }, "type": { "type": "enum", "values": [ "fill", "line", "symbol", "raster", "background" ], "doc": "Rendering type of this layer." }, "ref": { "type": "string", "doc": "References another layer to copy `type`, `source`, `source-layer`, `minzoom`, `maxzoom`, `filter`, and `layout` properties from. This allows the layers to share processing and be more efficient." }, "source": { "type": "string", "doc": "Name of a source description to be used for this layer." }, "source-layer": { "type": "string", "doc": "Layer to use from a vector tile source. Required if the source supports multiple layers." }, "minzoom": { "type": "number", "minimum": 0, "maximum": 22, "doc": "The minimum zoom level on which the layer gets parsed and appears on." }, "maxzoom": { "type": "number", "minimum": 0, "maximum": 22, "doc": "The maximum zoom level on which the layer gets parsed and appears on." }, "interactive": { "type": "boolean", "doc": "Enable querying of feature data from this layer for interactivity.", "default": false }, "filter": { "type": "filter", "doc": "A expression specifying conditions on source features. Only features that match the filter are displayed." }, "layout": { "type": "layout", "doc": "Layout properties for the layer." }, "paint": { "type": "paint", "doc": "Default paint properties for this layer." }, "paint.*": { "type": "paint", "doc": "Class-specific paint properties for this layer. The class name is the part after the first dot." } }, "layout": [ "layout_fill", "layout_line", "layout_symbol", "layout_raster", "layout_background" ], "layout_background": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_fill": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_line": { "line-cap": { "type": "enum", "function": "piecewise-constant", "values": [ "butt", "round", "square" ], "default": "butt", "doc": "The display of line endings." }, "line-join": { "type": "enum", "function": "piecewise-constant", "values": [ "bevel", "round", "miter" ], "default": "miter", "doc": "The display of lines when joining." }, "line-miter-limit": { "type": "number", "default": 2, "function": "interpolated", "doc": "Used to automatically convert miter joins to bevel joins for sharp angles.", "requires": [ { "line-join": "miter" } ] }, "line-round-limit": { "type": "number", "default": 1, "function": "interpolated", "doc": "Used to automatically convert round joins to miter joins for shallow angles.", "requires": [ { "line-join": "round" } ] }, "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_symbol": { "symbol-placement": { "type": "enum", "function": "piecewise-constant", "values": [ "point", "line" ], "default": "point", "doc": "Label placement relative to its geometry. `line` can only be used on LineStrings and Polygons." }, "symbol-min-distance": { "type": "number", "default": 250, "minimum": 1, "function": "interpolated", "units": "pixels", "doc": "Minimum distance between two symbol anchors.", "requires": [ { "symbol-placement": "line" } ] }, "symbol-avoid-edges": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer." }, "icon-allow-overlap": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon will be visible even if it collides with other icons and text.", "requires": [ "icon-image" ] }, "icon-ignore-placement": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon won't affect placement of other icons and text.", "requires": [ "icon-image" ] }, "icon-optional": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbol will appear without its icon, in spaces where the icon would make it too large to fit.", "requires": [ "icon-image", "text-field" ] }, "icon-rotation-alignment": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon when map is rotated.", "requires": [ "icon-image" ] }, "icon-max-size": { "type": "number", "default": 1, "minimum": 0, "function": "interpolated", "doc": "The maximum factor to scale the icon.", "requires": [ "icon-image" ] }, "icon-image": { "type": "string", "function": "piecewise-constant", "doc": "A string with {tokens} replaced, referencing the data property to pull from.", "tokens": true }, "icon-rotate": { "type": "number", "default": 0, "period": 360, "function": "interpolated", "units": "degrees", "doc": "Rotates the icon clockwise.", "requires": [ "icon-image" ] }, "icon-padding": { "type": "number", "default": 2, "minimum": 0, "function": "interpolated", "units": "pixels", "doc": "Padding value around icon bounding box to avoid icon collisions.", "requires": [ "icon-image" ] }, "icon-keep-upright": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the icon may be flipped to prevent it from being rendered upside-down", "requires": [ "icon-image", { "icon-rotation-alignment": "map" } ] }, "icon-offset": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "doc": "Icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "icon-image" ] }, "text-rotation-alignment": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon or text when map is rotated.", "requires": [ "text-field" ] }, "text-field": { "type": "string", "function": "piecewise-constant", "default": "", "tokens": true, "doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}." }, "text-font": { "type": "string", "function": "piecewise-constant", "default": "Open Sans Regular, Arial Unicode MS Regular", "doc": "Font stack to use for displaying text.", "requires": [ "text-field" ] }, "text-max-size": { "type": "number", "default": 16, "minimum": 0, "units": "pixels", "function": "interpolated", "doc": "The maximum size text will be laid out, to calculate collisions with.", "requires": [ "text-field" ] }, "text-max-width": { "type": "number", "default": 15, "minimum": 0, "units": "em", "function": "interpolated", "doc": "The maximum line width for text wrapping.", "requires": [ "text-field" ] }, "text-line-height": { "type": "number", "default": 1.2, "units": "em", "function": "interpolated", "doc": "Text leading value for multi-line text.", "requires": [ "text-field" ] }, "text-letter-spacing": { "type": "number", "default": 0, "units": "em", "function": "interpolated", "doc": "Text kerning value.", "requires": [ "text-field" ] }, "text-justify": { "type": "enum", "function": "piecewise-constant", "values": [ "left", "center", "right" ], "default": "center", "doc": "Text justification options.", "requires": [ "text-field" ] }, "text-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "center", "left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right" ], "default": "center", "doc": "Which part of the text to place closest to the anchor.", "requires": [ "text-field" ] }, "text-max-angle": { "type": "number", "default": 45, "units": "degrees", "function": "interpolated", "doc": "Maximum angle change between adjacent characters.", "requires": [ "text-field", { "symbol-placement": "line" } ] }, "text-rotate": { "type": "number", "default": 0, "period": 360, "units": "degrees", "function": "interpolated", "doc": "Rotates the text clockwise.", "requires": [ "text-field" ] }, "text-padding": { "type": "number", "default": 2, "minimum": 0, "units": "pixels", "function": "interpolated", "doc": "Padding value around text bounding box to avoid label collisions.", "requires": [ "text-field" ] }, "text-keep-upright": { "type": "boolean", "function": "piecewise-constant", "default": true, "doc": "If true, the text may be flipped vertically to prevent it from being rendered upside-down.", "requires": [ "text-field", { "text-rotation-alignment": "map" } ] }, "text-transform": { "type": "enum", "function": "piecewise-constant", "values": [ "none", "uppercase", "lowercase" ], "default": "none", "doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property.", "requires": [ "text-field" ] }, "text-offset": { "type": "array", "doc": "Specifies the distance that text is offset from its anchor horizontally and vertically.", "value": "number", "units": "ems", "function": "interpolated", "length": 2, "default": [ 0, 0 ], "requires": [ "text-field" ] }, "text-allow-overlap": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the text will be visible even if it collides with other icons and labels.", "requires": [ "text-field" ] }, "text-ignore-placement": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the text won't affect placement of other icons and labels.", "requires": [ "text-field" ] }, "text-optional": { "type": "boolean", "function": "piecewise-constant", "default": false, "doc": "If true, the symbol will appear without its text, in spaces where the text would make it too large to fit.", "requires": [ "text-field", "icon-image" ] }, "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "layout_raster": { "visibility": { "type": "enum", "function": "piecewise-constant", "values": [ "visible", "none" ], "default": "visible", "doc": "The display of this layer. `none` hides this layer." } }, "filter": { "type": "array", "value": "*" }, "filter_operator": { "type": "enum", "values": [ "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none" ] }, "geometry_type": { "type": "enum", "values": [ "Point", "LineString", "Polygon" ] }, "function": { "stops": { "type": "array", "required": true, "doc": "An array of stops.", "value": "function_stop" }, "base": { "type": "number", "default": 1, "minimum": 0, "doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly." } }, "function_stop": { "type": "array", "minimum": 0, "maximum": 22, "value": [ "number", "color" ], "length": 2, "doc": "Zoom level and value pair." }, "paint": [ "paint_fill", "paint_line", "paint_symbol", "paint_raster", "paint_background" ], "paint_fill": { "fill-antialias": { "type": "boolean", "function": "piecewise-constant", "default": true, "doc": "Whether or not the fill should be antialiased." }, "fill-opacity": { "type": "number", "function": "interpolated", "default": 1, "minimum": 0, "maximum": 1, "doc": "The opacity given to the fill color.", "transition": true }, "fill-color": { "type": "color", "default": "#000000", "doc": "The color of the fill.", "function": "interpolated", "transition": true, "requires": [ { "!": "fill-image" } ] }, "fill-outline-color": { "type": "color", "doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.", "function": "interpolated", "transition": true, "requires": [ { "!": "fill-image" }, { "fill-antialias": true } ] }, "fill-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." }, "fill-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "fill-translate" ] }, "fill-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Name of image in sprite to use for drawing image fills." } }, "paint_line": { "line-opacity": { "type": "number", "doc": "The opacity at which the line will be drawn.", "function": "interpolated", "default": 1, "minimum": 0, "maximum": 1, "transition": true }, "line-color": { "type": "color", "doc": "The color with which the line will be drawn.", "default": "#000000", "function": "interpolated", "transition": true, "requires": [ { "!": "line-image" } ] }, "line-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." }, "line-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "line-translate" ] }, "line-width": { "type": "number", "default": 1, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Stroke thickness." }, "line-gap-width": { "type": "number", "default": 0, "minimum": 0, "doc": "Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.", "function": "interpolated", "transition": true, "units": "pixels" }, "line-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Blur applied to the line, in pixels." }, "line-dasharray": { "type": "array", "function": "piecewise-constant", "value": "number", "doc": "Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.", "minimum": 0, "transition": true, "units": "line widths", "requires": [ { "!": "line-image" } ] }, "line-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Name of image in sprite to use for drawing image lines." } }, "paint_symbol": { "icon-opacity": { "doc": "The opacity at which the icon will be drawn.", "type": "number", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true, "requires": [ "icon-image" ] }, "icon-size": { "type": "number", "default": 1, "function": "interpolated", "transition": true, "doc": "Scale factor for icon. 1 is original size, 3 triples the size.", "requires": [ "icon-image" ] }, "icon-color": { "type": "color", "default": "#000000", "function": "interpolated", "transition": true, "doc": "The color of the icon. This can only be used with sdf icons.", "requires": [ "icon-image" ] }, "icon-halo-color": { "type": "color", "default": "rgba(0, 0, 0, 0)", "function": "interpolated", "transition": true, "doc": "The color of the icon's halo. Icon halos can only be used with sdf icons.", "requires": [ "icon-image" ] }, "icon-halo-width": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Distance of halo to the icon outline.", "requires": [ "icon-image" ] }, "icon-halo-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Fade out the halo towards the outside.", "requires": [ "icon-image" ] }, "icon-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "An icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "icon-image" ] }, "icon-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "icon-image", "icon-translate" ] }, "text-opacity": { "type": "number", "doc": "The opacity at which the text will be drawn.", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true, "requires": [ "text-field" ] }, "text-size": { "type": "number", "default": 16, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Font size. If unspecified, the text will be as big as allowed by the layer definition.", "requires": [ "text-field" ] }, "text-color": { "type": "color", "doc": "The color with which the text will be drawn.", "default": "#000000", "function": "interpolated", "transition": true, "requires": [ "text-field" ] }, "text-halo-color": { "type": "color", "default": "rgba(0, 0, 0, 0)", "function": "interpolated", "transition": true, "doc": "The color of the text's halo, which helps it stand out from backgrounds.", "requires": [ "text-field" ] }, "text-halo-width": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.", "requires": [ "text-field" ] }, "text-halo-blur": { "type": "number", "default": 0, "minimum": 0, "function": "interpolated", "transition": true, "units": "pixels", "doc": "The halo's fadeout distance towards the outside.", "requires": [ "text-field" ] }, "text-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": "interpolated", "transition": true, "units": "pixels", "doc": "Label offset. Values are [x, y] where negatives indicate left and up, respectively.", "requires": [ "text-field" ] }, "text-translate-anchor": { "type": "enum", "function": "piecewise-constant", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map", "requires": [ "text-field", "text-translate" ] } }, "paint_raster": { "raster-opacity": { "type": "number", "doc": "The opacity at which the image will be drawn.", "default": 1, "minimum": 0, "maximum": 1, "function": "interpolated", "transition": true }, "raster-hue-rotate": { "type": "number", "default": 0, "period": 360, "function": "interpolated", "transition": true, "units": "degrees", "doc": "Rotates hues around the color wheel." }, "raster-brightness-min": { "type": "number", "function": "interpolated", "doc": "Increase or reduce the brightness of the image. The value is the minimum brightness.", "default": 0, "minimum": 0, "maximum": 1, "transition": true }, "raster-brightness-max": { "type": "number", "function": "interpolated", "doc": "Increase or reduce the brightness of the image. The value is the maximum brightness.", "default": 1, "minimum": 0, "maximum": 1, "transition": true }, "raster-saturation": { "type": "number", "doc": "Increase or reduce the saturation of the image.", "default": 0, "minimum": -1, "maximum": 1, "function": "interpolated", "transition": true }, "raster-contrast": { "type": "number", "doc": "Increase or reduce the contrast of the image.", "default": 0, "minimum": -1, "maximum": 1, "function": "interpolated", "transition": true }, "raster-fade-duration": { "type": "number", "default": 300, "minimum": 0, "function": "interpolated", "transition": true, "units": "milliseconds", "doc": "Fade duration when a new tile is added." } }, "paint_background": { "background-color": { "type": "color", "default": "#000000", "doc": "The color with which the background will be drawn.", "function": "interpolated", "transition": true, "requires": [ { "!": "background-image" } ] }, "background-image": { "type": "string", "function": "piecewise-constant", "transition": true, "doc": "Optionally an image which is drawn as the background." }, "background-opacity": { "type": "number", "default": 1, "minimum": 0, "maximum": 1, "doc": "The opacity at which the background will be drawn.", "function": "interpolated", "transition": true } }, "transition": { "duration": { "type": "number", "default": 300, "minimum": 0, "units": "milliseconds", "doc": "Time allotted for transitions to complete." }, "delay": { "type": "number", "default": 0, "minimum": 0, "units": "milliseconds", "doc": "Length of time before a transition begins." } } } },{}],110:[function(require,module,exports){ 'use strict'; // lightweight Buffer shim for pbf browser build // based on code from github.com/feross/buffer (MIT-licensed) module.exports = Buffer; var ieee754 = require('ieee754'); var BufferMethods; function Buffer(length) { var arr; if (length && length.length) { arr = length; length = arr.length; } var buf = new Uint8Array(length || 0); if (arr) buf.set(arr); buf.readUInt32LE = BufferMethods.readUInt32LE; buf.writeUInt32LE = BufferMethods.writeUInt32LE; buf.readInt32LE = BufferMethods.readInt32LE; buf.writeInt32LE = BufferMethods.writeInt32LE; buf.readFloatLE = BufferMethods.readFloatLE; buf.writeFloatLE = BufferMethods.writeFloatLE; buf.readDoubleLE = BufferMethods.readDoubleLE; buf.writeDoubleLE = BufferMethods.writeDoubleLE; buf.toString = BufferMethods.toString; buf.write = BufferMethods.write; buf.slice = BufferMethods.slice; buf.copy = BufferMethods.copy; buf._isBuffer = true; return buf; } var lastStr, lastStrEncoded; BufferMethods = { readUInt32LE: function(pos) { return ((this[pos]) | (this[pos + 1] << 8) | (this[pos + 2] << 16)) + (this[pos + 3] * 0x1000000); }, writeUInt32LE: function(val, pos) { this[pos] = val; this[pos + 1] = (val >>> 8); this[pos + 2] = (val >>> 16); this[pos + 3] = (val >>> 24); }, readInt32LE: function(pos) { return ((this[pos]) | (this[pos + 1] << 8) | (this[pos + 2] << 16)) + (this[pos + 3] << 24); }, readFloatLE: function(pos) { return ieee754.read(this, pos, true, 23, 4); }, readDoubleLE: function(pos) { return ieee754.read(this, pos, true, 52, 8); }, writeFloatLE: function(val, pos) { return ieee754.write(this, val, pos, true, 23, 4); }, writeDoubleLE: function(val, pos) { return ieee754.write(this, val, pos, true, 52, 8); }, toString: function(encoding, start, end) { var str = '', tmp = ''; start = start || 0; end = Math.min(this.length, end || this.length); for (var i = start; i < end; i++) { var ch = this[i]; if (ch <= 0x7F) { str += decodeURIComponent(tmp) + String.fromCharCode(ch); tmp = ''; } else { tmp += '%' + ch.toString(16); } } str += decodeURIComponent(tmp); return str; }, write: function(str, pos) { var bytes = str === lastStr ? lastStrEncoded : encodeString(str); for (var i = 0; i < bytes.length; i++) { this[pos + i] = bytes[i]; } }, slice: function(start, end) { return this.subarray(start, end); }, copy: function(buf, pos) { pos = pos || 0; for (var i = 0; i < this.length; i++) { buf[pos + i] = this[i]; } } }; BufferMethods.writeInt32LE = BufferMethods.writeUInt32LE; Buffer.byteLength = function(str) { lastStr = str; lastStrEncoded = encodeString(str); return lastStrEncoded.length; }; Buffer.isBuffer = function(buf) { return !!(buf && buf._isBuffer); }; function encodeString(str) { var length = str.length, bytes = []; for (var i = 0, c, lead; i < length; i++) { c = str.charCodeAt(i); // code point if (c > 0xD7FF && c < 0xE000) { if (lead) { if (c < 0xDC00) { bytes.push(0xEF, 0xBF, 0xBD); lead = c; continue; } else { c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000; lead = null; } } else { if (c > 0xDBFF || (i + 1 === length)) bytes.push(0xEF, 0xBF, 0xBD); else lead = c; continue; } } else if (lead) { bytes.push(0xEF, 0xBF, 0xBD); lead = null; } if (c < 0x80) bytes.push(c); else if (c < 0x800) bytes.push(c >> 0x6 | 0xC0, c & 0x3F | 0x80); else if (c < 0x10000) bytes.push(c >> 0xC | 0xE0, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80); else bytes.push(c >> 0x12 | 0xF0, c >> 0xC & 0x3F | 0x80, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80); } return bytes; } },{"ieee754":112}],111:[function(require,module,exports){ (function (global){ 'use strict'; module.exports = Pbf; var Buffer = global.Buffer || require('./buffer'); function Pbf(buf) { this.buf = !Buffer.isBuffer(buf) ? new Buffer(buf || 0) : buf; this.pos = 0; this.length = this.buf.length; } Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64 Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32 var SHIFT_LEFT_32 = (1 << 16) * (1 << 16), SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32, POW_2_63 = Math.pow(2, 63); Pbf.prototype = { destroy: function() { this.buf = null; }, // === READING ================================================================= readFields: function(readField, result, end) { end = end || this.length; while (this.pos < end) { var val = this.readVarint(), tag = val >> 3, startPos = this.pos; readField(tag, result, this); if (this.pos === startPos) this.skip(val); } return result; }, readMessage: function(readField, result) { return this.readFields(readField, result, this.readVarint() + this.pos); }, readFixed32: function() { var val = this.buf.readUInt32LE(this.pos); this.pos += 4; return val; }, readSFixed32: function() { var val = this.buf.readInt32LE(this.pos); this.pos += 4; return val; }, // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed) readFixed64: function() { var val = this.buf.readUInt32LE(this.pos) + this.buf.readUInt32LE(this.pos + 4) * SHIFT_LEFT_32; this.pos += 8; return val; }, readSFixed64: function() { var val = this.buf.readUInt32LE(this.pos) + this.buf.readInt32LE(this.pos + 4) * SHIFT_LEFT_32; this.pos += 8; return val; }, readFloat: function() { var val = this.buf.readFloatLE(this.pos); this.pos += 4; return val; }, readDouble: function() { var val = this.buf.readDoubleLE(this.pos); this.pos += 8; return val; }, readVarint: function() { var buf = this.buf, val, b, b0, b1, b2, b3; b0 = buf[this.pos++]; if (b0 < 0x80) return b0; b0 = b0 & 0x7f; b1 = buf[this.pos++]; if (b1 < 0x80) return b0 | b1 << 7; b1 = (b1 & 0x7f) << 7; b2 = buf[this.pos++]; if (b2 < 0x80) return b0 | b1 | b2 << 14; b2 = (b2 & 0x7f) << 14; b3 = buf[this.pos++]; if (b3 < 0x80) return b0 | b1 | b2 | b3 << 21; val = b0 | b1 | b2 | (b3 & 0x7f) << 21; b = buf[this.pos++]; val += (b & 0x7f) * 0x10000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x800000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x40000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x2000000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x100000000000000; if (b < 0x80) return val; b = buf[this.pos++]; val += (b & 0x7f) * 0x8000000000000000; if (b < 0x80) return val; throw new Error('Expected varint not more than 10 bytes'); }, readVarint64: function() { var startPos = this.pos, val = this.readVarint(); if (val < POW_2_63) return val; var pos = this.pos - 2; while (this.buf[pos] === 0xff) pos--; if (pos < startPos) pos = startPos; val = 0; for (var i = 0; i < pos - startPos + 1; i++) { var b = ~this.buf[startPos + i] & 0x7f; val += i < 4 ? b << i * 7 : b * Math.pow(2, i * 7); } return -val - 1; }, readSVarint: function() { var num = this.readVarint(); return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding }, readBoolean: function() { return Boolean(this.readVarint()); }, readString: function() { var end = this.readVarint() + this.pos, str = this.buf.toString('utf8', this.pos, end); this.pos = end; return str; }, readBytes: function() { var end = this.readVarint() + this.pos, buffer = this.buf.slice(this.pos, end); this.pos = end; return buffer; }, // verbose for performance reasons; doesn't affect gzipped size readPackedVarint: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readVarint()); return arr; }, readPackedSVarint: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSVarint()); return arr; }, readPackedBoolean: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readBoolean()); return arr; }, readPackedFloat: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFloat()); return arr; }, readPackedDouble: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readDouble()); return arr; }, readPackedFixed32: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFixed32()); return arr; }, readPackedSFixed32: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSFixed32()); return arr; }, readPackedFixed64: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readFixed64()); return arr; }, readPackedSFixed64: function() { var end = this.readVarint() + this.pos, arr = []; while (this.pos < end) arr.push(this.readSFixed64()); return arr; }, skip: function(val) { var type = val & 0x7; if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {} else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos; else if (type === Pbf.Fixed32) this.pos += 4; else if (type === Pbf.Fixed64) this.pos += 8; else throw new Error('Unimplemented type: ' + type); }, // === WRITING ================================================================= writeTag: function(tag, type) { this.writeVarint((tag << 3) | type); }, realloc: function(min) { var length = this.length || 16; while (length < this.pos + min) length *= 2; if (length !== this.length) { var buf = new Buffer(length); this.buf.copy(buf); this.buf = buf; this.length = length; } }, finish: function() { this.length = this.pos; this.pos = 0; return this.buf.slice(0, this.length); }, writeFixed32: function(val) { this.realloc(4); this.buf.writeUInt32LE(val, this.pos); this.pos += 4; }, writeSFixed32: function(val) { this.realloc(4); this.buf.writeInt32LE(val, this.pos); this.pos += 4; }, writeFixed64: function(val) { this.realloc(8); this.buf.writeInt32LE(val & -1, this.pos); this.buf.writeUInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4); this.pos += 8; }, writeSFixed64: function(val) { this.realloc(8); this.buf.writeInt32LE(val & -1, this.pos); this.buf.writeInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4); this.pos += 8; }, writeVarint: function(val) { val = +val; if (val <= 0x7f) { this.realloc(1); this.buf[this.pos++] = val; } else if (val <= 0x3fff) { this.realloc(2); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f); } else if (val <= 0x1fffff) { this.realloc(3); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 14) & 0x7f); } else if (val <= 0xfffffff) { this.realloc(4); this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 14) & 0x7f) | 0x80; this.buf[this.pos++] = ((val >>> 21) & 0x7f); } else { var pos = this.pos; while (val >= 0x80) { this.realloc(1); this.buf[this.pos++] = (val & 0xff) | 0x80; val /= 0x80; } this.realloc(1); this.buf[this.pos++] = val | 0; if (this.pos - pos > 10) throw new Error('Given varint doesn\'t fit into 10 bytes'); } }, writeSVarint: function(val) { this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2); }, writeBoolean: function(val) { this.writeVarint(Boolean(val)); }, writeString: function(str) { str = String(str); var bytes = Buffer.byteLength(str); this.writeVarint(bytes); this.realloc(bytes); this.buf.write(str, this.pos); this.pos += bytes; }, writeFloat: function(val) { this.realloc(4); this.buf.writeFloatLE(val, this.pos); this.pos += 4; }, writeDouble: function(val) { this.realloc(8); this.buf.writeDoubleLE(val, this.pos); this.pos += 8; }, writeBytes: function(buffer) { var len = buffer.length; this.writeVarint(len); this.realloc(len); for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i]; }, writeMessage: function(tag, fn, obj) { this.writeTag(tag, Pbf.Bytes); this.pos++; // reserve 1 byte for short message length // write the message directly to the buffer and see how much was written var startPos = this.pos; fn(obj, this); var len = this.pos - startPos; var varintLen = len <= 0x7f ? 1 : len <= 0x3fff ? 2 : len <= 0x1fffff ? 3 : len <= 0xfffffff ? 4 : Math.ceil(Math.log(len) / (Math.LN2 * 7)); // if 1 byte isn't enough for encoding message length, shift the data to the right if (varintLen > 1) { this.realloc(varintLen - 1); for (var i = this.pos - 1; i >= startPos; i--) this.buf[i + varintLen - 1] = this.buf[i]; } // finally, write the message length in the reserved place and restore the position this.pos = startPos - 1; this.writeVarint(len); this.pos += len; }, writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); }, writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); }, writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); }, writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); }, writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); }, writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); }, writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); }, writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); }, writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); }, writeBytesField: function(tag, buffer) { this.writeTag(tag, Pbf.Bytes); this.writeBytes(buffer); }, writeFixed32Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeFixed32(val); }, writeSFixed32Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeSFixed32(val); }, writeFixed64Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeFixed64(val); }, writeSFixed64Field: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeSFixed64(val); }, writeVarintField: function(tag, val) { this.writeTag(tag, Pbf.Varint); this.writeVarint(val); }, writeSVarintField: function(tag, val) { this.writeTag(tag, Pbf.Varint); this.writeSVarint(val); }, writeStringField: function(tag, str) { this.writeTag(tag, Pbf.Bytes); this.writeString(str); }, writeFloatField: function(tag, val) { this.writeTag(tag, Pbf.Fixed32); this.writeFloat(val); }, writeDoubleField: function(tag, val) { this.writeTag(tag, Pbf.Fixed64); this.writeDouble(val); }, writeBooleanField: function(tag, val) { this.writeVarintField(tag, Boolean(val)); } }; function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]); } function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]); } function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]); } function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]); } function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]); } function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]); } function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); } function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]); } function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./buffer":110}],112:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, nBits = -7, i = isLE ? (nBytes - 1) : 0, d = isLE ? -1 : 1, s = buffer[offset + i] i += d e = s & ((1 << (-nBits)) - 1) s >>= (-nBits) nBits += eLen for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} m = e & ((1 << (-nBits)) - 1) e >>= (-nBits) nBits += mLen for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { e = 1 - eBias } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { m = m + Math.pow(2, mLen) e = e - eBias } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) } exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { var e, m, c, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), i = isLE ? 0 : (nBytes - 1), d = isLE ? 1 : -1, s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 value = Math.abs(value) if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0 e = eMax } else { e = Math.floor(Math.log(value) / Math.LN2) if (value * (c = Math.pow(2, -e)) < 1) { e-- c *= 2 } if (e + eBias >= 1) { value += rt / c } else { value += rt * Math.pow(2, 1 - eBias) } if (value * c >= 2) { e++ c /= 2 } if (e + eBias >= eMax) { m = 0 e = eMax } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen) e = e + eBias } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) e = 0 } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} e = (e << mLen) | m eLen += mLen for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128 } },{}],113:[function(require,module,exports){ 'use strict'; module.exports = Point; function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { clone: function() { return new Point(this.x, this.y); }, add: function(p) { return this.clone()._add(p); }, sub: function(p) { return this.clone()._sub(p); }, mult: function(k) { return this.clone()._mult(k); }, div: function(k) { return this.clone()._div(k); }, rotate: function(a) { return this.clone()._rotate(a); }, matMult: function(m) { return this.clone()._matMult(m); }, unit: function() { return this.clone()._unit(); }, perp: function() { return this.clone()._perp(); }, round: function() { return this.clone()._round(); }, mag: function() { return Math.sqrt(this.x * this.x + this.y * this.y); }, equals: function(p) { return this.x === p.x && this.y === p.y; }, dist: function(p) { return Math.sqrt(this.distSqr(p)); }, distSqr: function(p) { var dx = p.x - this.x, dy = p.y - this.y; return dx * dx + dy * dy; }, angle: function() { return Math.atan2(this.y, this.x); }, angleTo: function(b) { return Math.atan2(this.y - b.y, this.x - b.x); }, angleWith: function(b) { return this.angleWithSep(b.x, b.y); }, // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ. angleWithSep: function(x, y) { return Math.atan2( this.x * y - this.y * x, this.x * x + this.y * y); }, _matMult: function(m) { var x = m[0] * this.x + m[1] * this.y, y = m[2] * this.x + m[3] * this.y; this.x = x; this.y = y; return this; }, _add: function(p) { this.x += p.x; this.y += p.y; return this; }, _sub: function(p) { this.x -= p.x; this.y -= p.y; return this; }, _mult: function(k) { this.x *= k; this.y *= k; return this; }, _div: function(k) { this.x /= k; this.y /= k; return this; }, _unit: function() { this._div(this.mag()); return this; }, _perp: function() { var y = this.y; this.y = this.x; this.x = -y; return this; }, _rotate: function(angle) { var cos = Math.cos(angle), sin = Math.sin(angle), x = cos * this.x - sin * this.y, y = sin * this.x + cos * this.y; this.x = x; this.y = y; return this; }, _round: function() { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; } }; // constructs Point from an array if necessary Point.convert = function (a) { if (a instanceof Point) { return a; } if (Array.isArray(a)) { return new Point(a[0], a[1]); } return a; }; },{}],114:[function(require,module,exports){ /* (c) 2013, Vladimir Agafonkin RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles. https://github.com/mourner/rbush */ (function () { 'use strict'; function rbush(maxEntries, format) { // jshint newcap: false, validthis: true if (!(this instanceof rbush)) return new rbush(maxEntries, format); // max entries in a node is 9 by default; min node fill is 40% for best performance this._maxEntries = Math.max(4, maxEntries || 9); this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); if (format) { this._initFormat(format); } this.clear(); } rbush.prototype = { all: function () { return this._all(this.data, []); }, search: function (bbox) { var node = this.data, result = [], toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return result; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf) result.push(child); else if (contains(bbox, childBBox)) this._all(child, result); else nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return result; }, collides: function (bbox) { var node = this.data, toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return false; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf || contains(bbox, childBBox)) return true; nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return false; }, load: function (data) { if (!(data && data.length)) return this; if (data.length < this._minEntries) { for (var i = 0, len = data.length; i < len; i++) { this.insert(data[i]); } return this; } // recursively build the tree with the given data from stratch using OMT algorithm var node = this._build(data.slice(), 0, data.length - 1, 0); if (!this.data.children.length) { // save as is if tree is empty this.data = node; } else if (this.data.height === node.height) { // split root if trees have the same height this._splitRoot(this.data, node); } else { if (this.data.height < node.height) { // swap trees if inserted one is bigger var tmpNode = this.data; this.data = node; node = tmpNode; } // insert the small tree into the large tree at appropriate level this._insert(node, this.data.height - node.height - 1, true); } return this; }, insert: function (item) { if (item) this._insert(item, this.data.height - 1); return this; }, clear: function () { this.data = { children: [], height: 1, bbox: empty(), leaf: true }; return this; }, remove: function (item) { if (!item) return this; var node = this.data, bbox = this.toBBox(item), path = [], indexes = [], i, parent, index, goingUp; // depth-first iterative tree traversal while (node || path.length) { if (!node) { // go up node = path.pop(); parent = path[path.length - 1]; i = indexes.pop(); goingUp = true; } if (node.leaf) { // check current node index = node.children.indexOf(item); if (index !== -1) { // item found, remove the item and condense tree upwards node.children.splice(index, 1); path.push(node); this._condense(path); return this; } } if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down path.push(node); indexes.push(i); i = 0; parent = node; node = node.children[0]; } else if (parent) { // go right i++; node = parent.children[i]; goingUp = false; } else node = null; // nothing found } return this; }, toBBox: function (item) { return item; }, compareMinX: function (a, b) { return a[0] - b[0]; }, compareMinY: function (a, b) { return a[1] - b[1]; }, toJSON: function () { return this.data; }, fromJSON: function (data) { this.data = data; return this; }, _all: function (node, result) { var nodesToSearch = []; while (node) { if (node.leaf) result.push.apply(result, node.children); else nodesToSearch.push.apply(nodesToSearch, node.children); node = nodesToSearch.pop(); } return result; }, _build: function (items, left, right, height) { var N = right - left + 1, M = this._maxEntries, node; if (N <= M) { // reached leaf level; return leaf node = { children: items.slice(left, right + 1), height: 1, bbox: null, leaf: true }; calcBBox(node, this.toBBox); return node; } if (!height) { // target height of the bulk-loaded tree height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization M = Math.ceil(N / Math.pow(M, height - 1)); } // TODO eliminate recursion? node = { children: [], height: height, bbox: null }; // split the items into M mostly square tiles var N2 = Math.ceil(N / M), N1 = N2 * Math.ceil(Math.sqrt(M)), i, j, right2, right3; multiSelect(items, left, right, N1, this.compareMinX); for (i = left; i <= right; i += N1) { right2 = Math.min(i + N1 - 1, right); multiSelect(items, i, right2, N2, this.compareMinY); for (j = i; j <= right2; j += N2) { right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively node.children.push(this._build(items, j, right3, height - 1)); } } calcBBox(node, this.toBBox); return node; }, _chooseSubtree: function (bbox, node, level, path) { var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; while (true) { path.push(node); if (node.leaf || path.length - 1 === level) break; minArea = minEnlargement = Infinity; for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; area = bboxArea(child.bbox); enlargement = enlargedArea(bbox, child.bbox) - area; // choose entry with the least area enlargement if (enlargement < minEnlargement) { minEnlargement = enlargement; minArea = area < minArea ? area : minArea; targetNode = child; } else if (enlargement === minEnlargement) { // otherwise choose one with the smallest area if (area < minArea) { minArea = area; targetNode = child; } } } node = targetNode; } return node; }, _insert: function (item, level, isNode) { var toBBox = this.toBBox, bbox = isNode ? item.bbox : toBBox(item), insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node node.children.push(item); extend(node.bbox, bbox); // split on node overflow; propagate upwards if necessary while (level >= 0) { if (insertPath[level].children.length > this._maxEntries) { this._split(insertPath, level); level--; } else break; } // adjust bboxes along the insertion path this._adjustParentBBoxes(bbox, insertPath, level); }, // split overflowed node into two _split: function (insertPath, level) { var node = insertPath[level], M = node.children.length, m = this._minEntries; this._chooseSplitAxis(node, m, M); var newNode = { children: node.children.splice(this._chooseSplitIndex(node, m, M)), height: node.height }; if (node.leaf) newNode.leaf = true; calcBBox(node, this.toBBox); calcBBox(newNode, this.toBBox); if (level) insertPath[level - 1].children.push(newNode); else this._splitRoot(node, newNode); }, _splitRoot: function (node, newNode) { // split root node this.data = { children: [node, newNode], height: node.height + 1 }; calcBBox(this.data, this.toBBox); }, _chooseSplitIndex: function (node, m, M) { var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; minOverlap = minArea = Infinity; for (i = m; i <= M - m; i++) { bbox1 = distBBox(node, 0, i, this.toBBox); bbox2 = distBBox(node, i, M, this.toBBox); overlap = intersectionArea(bbox1, bbox2); area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap if (overlap < minOverlap) { minOverlap = overlap; index = i; minArea = area < minArea ? area : minArea; } else if (overlap === minOverlap) { // otherwise choose distribution with minimum area if (area < minArea) { minArea = area; index = i; } } } return index; }, // sorts node children by the best axis for split _chooseSplitAxis: function (node, m, M) { var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, xMargin = this._allDistMargin(node, m, M, compareMinX), yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX, // otherwise it's already sorted by minY if (xMargin < yMargin) node.children.sort(compareMinX); }, // total margin of all possible split distributions where each node is at least m full _allDistMargin: function (node, m, M, compare) { node.children.sort(compare); var toBBox = this.toBBox, leftBBox = distBBox(node, 0, m, toBBox), rightBBox = distBBox(node, M - m, M, toBBox), margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), i, child; for (i = m; i < M - m; i++) { child = node.children[i]; extend(leftBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(leftBBox); } for (i = M - m - 1; i >= m; i--) { child = node.children[i]; extend(rightBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(rightBBox); } return margin; }, _adjustParentBBoxes: function (bbox, path, level) { // adjust bboxes along the given tree path for (var i = level; i >= 0; i--) { extend(path[i].bbox, bbox); } }, _condense: function (path) { // go through the path, removing empty nodes and updating bboxes for (var i = path.length - 1, siblings; i >= 0; i--) { if (path[i].children.length === 0) { if (i > 0) { siblings = path[i - 1].children; siblings.splice(siblings.indexOf(path[i]), 1); } else this.clear(); } else calcBBox(path[i], this.toBBox); } }, _initFormat: function (format) { // data format (minX, minY, maxX, maxY accessors) // uses eval-type function compilation instead of just accepting a toBBox function // because the algorithms are very sensitive to sorting functions performance, // so they should be dead simple and without inner calls // jshint evil: true var compareArr = ['return a', ' - b', ';']; this.compareMinX = new Function('a', 'b', compareArr.join(format[0])); this.compareMinY = new Function('a', 'b', compareArr.join(format[1])); this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];'); } }; // calculate node's bbox from bboxes of its children function calcBBox(node, toBBox) { node.bbox = distBBox(node, 0, node.children.length, toBBox); } // min bounding rectangle of node children from k to p-1 function distBBox(node, k, p, toBBox) { var bbox = empty(); for (var i = k, child; i < p; i++) { child = node.children[i]; extend(bbox, node.leaf ? toBBox(child) : child.bbox); } return bbox; } function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; } function extend(a, b) { a[0] = Math.min(a[0], b[0]); a[1] = Math.min(a[1], b[1]); a[2] = Math.max(a[2], b[2]); a[3] = Math.max(a[3], b[3]); return a; } function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; } function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; } function bboxArea(a) { return (a[2] - a[0]) * (a[3] - a[1]); } function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); } function enlargedArea(a, b) { return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) * (Math.max(b[3], a[3]) - Math.min(b[1], a[1])); } function intersectionArea(a, b) { var minX = Math.max(a[0], b[0]), minY = Math.max(a[1], b[1]), maxX = Math.min(a[2], b[2]), maxY = Math.min(a[3], b[3]); return Math.max(0, maxX - minX) * Math.max(0, maxY - minY); } function contains(a, b) { return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3]; } function intersects(a, b) { return b[0] <= a[2] && b[1] <= a[3] && b[2] >= a[0] && b[3] >= a[1]; } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other; // combines selection algorithm with binary divide & conquer approach function multiSelect(arr, left, right, n, compare) { var stack = [left, right], mid; while (stack.length) { right = stack.pop(); left = stack.pop(); if (right - left <= n) continue; mid = left + Math.ceil((right - left) / n / 2) * n; select(arr, left, right, mid, compare); stack.push(left, mid, mid, right); } } // Floyd-Rivest selection algorithm: // sort an array between left and right (inclusive) so that the smallest k elements come first (unordered) function select(arr, left, right, k, compare) { var n, i, z, s, sd, newLeft, newRight, t, j; while (right > left) { if (right - left > 600) { n = right - left + 1; i = k - left + 1; z = Math.log(n); s = 0.5 * Math.exp(2 * z / 3); sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1); newLeft = Math.max(left, Math.floor(k - i * s / n + sd)); newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd)); select(arr, newLeft, newRight, k, compare); } t = arr[k]; i = left; j = right; swap(arr, left, k); if (compare(arr[right], t) > 0) swap(arr, left, right); while (i < j) { swap(arr, i, j); i++; j--; while (compare(arr[i], t) < 0) i++; while (compare(arr[j], t) > 0) j--; } if (compare(arr[left], t) === 0) swap(arr, left, j); else { j++; swap(arr, j, right); } if (j <= k) left = j + 1; if (k <= j) right = j - 1; } } function swap(arr, i, j) { var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } // export as AMD/CommonJS module or global variable if (typeof define === 'function' && define.amd) define('rbush', function() { return rbush; }); else if (typeof module !== 'undefined') module.exports = rbush; else if (typeof self !== 'undefined') self.rbush = rbush; else window.rbush = rbush; })(); },{}],115:[function(require,module,exports){ // Copyright 2014 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) void (function(root, factory) { if (typeof define === "function" && define.amd) { define(factory) } else if (typeof exports === "object") { module.exports = factory() } else { root.resolveUrl = factory() } }(this, function() { function resolveUrl(/* ...urls */) { var numUrls = arguments.length if (numUrls === 0) { throw new Error("resolveUrl requires at least one argument; got none.") } var base = document.createElement("base") base.href = arguments[0] if (numUrls === 1) { return base.href } var head = document.getElementsByTagName("head")[0] head.insertBefore(base, head.firstChild) var a = document.createElement("a") var resolved for (var index = 1; index < numUrls; index++) { a.href = arguments[index] resolved = a.href base.href = resolved } head.removeChild(base) return resolved } return resolveUrl })); },{}],116:[function(require,module,exports){ /* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Ported from Webkit * http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h */ module.exports = UnitBezier; function UnitBezier(p1x, p1y, p2x, p2y) { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). this.cx = 3.0 * p1x; this.bx = 3.0 * (p2x - p1x) - this.cx; this.ax = 1.0 - this.cx - this.bx; this.cy = 3.0 * p1y; this.by = 3.0 * (p2y - p1y) - this.cy; this.ay = 1.0 - this.cy - this.by; this.p1x = p1x; this.p1y = p2y; this.p2x = p2x; this.p2y = p2y; } UnitBezier.prototype.sampleCurveX = function(t) { // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. return ((this.ax * t + this.bx) * t + this.cx) * t; }; UnitBezier.prototype.sampleCurveY = function(t) { return ((this.ay * t + this.by) * t + this.cy) * t; }; UnitBezier.prototype.sampleCurveDerivativeX = function(t) { return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx; }; UnitBezier.prototype.solveCurveX = function(x, epsilon) { if (typeof epsilon === 'undefined') epsilon = 1e-6; var t0, t1, t2, x2, i; // First try a few iterations of Newton's method -- normally very fast. for (t2 = x, i = 0; i < 8; i++) { x2 = this.sampleCurveX(t2) - x; if (Math.abs(x2) < epsilon) return t2; var d2 = this.sampleCurveDerivativeX(t2); if (Math.abs(d2) < 1e-6) break; t2 = t2 - x2 / d2; } // Fall back to the bisection method for reliability. t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) return t0; if (t2 > t1) return t1; while (t0 < t1) { x2 = this.sampleCurveX(t2); if (Math.abs(x2 - x) < epsilon) return t2; if (x > x2) { t0 = t2; } else { t1 = t2; } t2 = (t1 - t0) * 0.5 + t0; } // Failure. return t2; }; UnitBezier.prototype.solve = function(x, epsilon) { return this.sampleCurveY(this.solveCurveX(x, epsilon)); }; },{}],117:[function(require,module,exports){ module.exports.VectorTile = require('./lib/vectortile.js'); module.exports.VectorTileFeature = require('./lib/vectortilefeature.js'); module.exports.VectorTileLayer = require('./lib/vectortilelayer.js'); },{"./lib/vectortile.js":118,"./lib/vectortilefeature.js":119,"./lib/vectortilelayer.js":120}],118:[function(require,module,exports){ 'use strict'; var VectorTileLayer = require('./vectortilelayer'); module.exports = VectorTile; function VectorTile(pbf, end) { this.layers = pbf.readFields(readTile, {}, end); } function readTile(tag, layers, pbf) { if (tag === 3) { var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos); if (layer.length) layers[layer.name] = layer; } } },{"./vectortilelayer":120}],119:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = VectorTileFeature; function VectorTileFeature(pbf, end, extent, keys, values) { // Public this.properties = {}; this.extent = extent; this.type = 0; // Private this._pbf = pbf; this._geometry = -1; this._keys = keys; this._values = values; pbf.readFields(readFeature, this, end); } function readFeature(tag, feature, pbf) { if (tag == 1) feature._id = pbf.readVarint(); else if (tag == 2) readTag(pbf, feature); else if (tag == 3) feature.type = pbf.readVarint(); else if (tag == 4) feature._geometry = pbf.pos; } function readTag(pbf, feature) { var end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { var key = feature._keys[pbf.readVarint()], value = feature._values[pbf.readVarint()]; feature.properties[key] = value; } } VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon']; VectorTileFeature.prototype.loadGeometry = function() { var pbf = this._pbf; pbf.pos = this._geometry; var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, lines = [], line; while (pbf.pos < end) { if (!length) { var cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (cmd === 1) { // moveTo if (line) lines.push(line); line = []; } line.push(new Point(x, y)); } else if (cmd === 7) { line.push(line[0].clone()); // closePolygon } else { throw new Error('unknown command ' + cmd); } } if (line) lines.push(line); return lines; }; VectorTileFeature.prototype.bbox = function() { var pbf = this._pbf; pbf.pos = this._geometry; var end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, y = 0, x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity; while (pbf.pos < end) { if (!length) { var cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (x < x1) x1 = x; if (x > x2) x2 = x; if (y < y1) y1 = y; if (y > y2) y2 = y; } else if (cmd !== 7) { throw new Error('unknown command ' + cmd); } } return [x1, y1, x2, y2]; }; VectorTileFeature.prototype.toGeoJSON = function(x, y, z) { var size = this.extent * Math.pow(2, z), x0 = this.extent * x, y0 = this.extent * y, coords = this.loadGeometry(), type = VectorTileFeature.types[this.type]; for (var i = 0; i < coords.length; i++) { var line = coords[i]; for (var j = 0; j < line.length; j++) { var p = line[j], y2 = 180 - (p.y + y0) * 360 / size; line[j] = [ (p.x + x0) * 360 / size - 180, 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90 ]; } } if (type === 'Point' && coords.length === 1) { coords = coords[0][0]; } else if (type === 'Point') { coords = coords[0]; type = 'MultiPoint'; } else if (type === 'LineString' && coords.length === 1) { coords = coords[0]; } else if (type === 'LineString') { type = 'MultiLineString'; } return { type: "Feature", geometry: { type: type, coordinates: coords }, properties: this.properties }; }; },{"point-geometry":113}],120:[function(require,module,exports){ 'use strict'; var VectorTileFeature = require('./vectortilefeature.js'); module.exports = VectorTileLayer; function VectorTileLayer(pbf, end) { // Public this.version = 1; this.name = null; this.extent = 4096; this.length = 0; // Private this._pbf = pbf; this._keys = []; this._values = []; this._features = []; pbf.readFields(readLayer, this, end); this.length = this._features.length; } function readLayer(tag, layer, pbf) { if (tag === 15) layer.version = pbf.readVarint(); else if (tag === 1) layer.name = pbf.readString(); else if (tag === 5) layer.extent = pbf.readVarint(); else if (tag === 2) layer._features.push(pbf.pos); else if (tag === 3) layer._keys.push(pbf.readString()); else if (tag === 4) layer._values.push(readValueMessage(pbf)); } function readValueMessage(pbf) { var value = null, end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { var tag = pbf.readVarint() >> 3; value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null; } return value; } // return feature `i` from this layer as a `VectorTileFeature` VectorTileLayer.prototype.feature = function(i) { if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds'); this._pbf.pos = this._features[i]; var end = this._pbf.readVarint() + this._pbf.pos; return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values); }; },{"./vectortilefeature.js":119}],121:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } },{}],122:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = setTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { currentQueue[queueIndex].run(); } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; clearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { setTimeout(drainQueue, 0); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],123:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } },{}],124:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (!isString(f)) { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': try { return JSON.stringify(args[i++]); } catch (_) { return '[Circular]'; } default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (isNull(x) || !isObject(x)) { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { // Allow for deprecating things in the process of starting up. if (isUndefined(global.process)) { return function() { return exports.deprecate(fn, msg).apply(this, arguments); }; } if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; var debugs = {}; var debugEnviron; exports.debuglog = function(set) { if (isUndefined(debugEnviron)) debugEnviron = process.env.NODE_DEBUG || ''; set = set.toUpperCase(); if (!debugs[set]) { if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { var pid = process.pid; debugs[set] = function() { var msg = exports.format.apply(exports, arguments); console.error('%s %d: %s', set, pid, msg); }; } else { debugs[set] = function() {}; } } return debugs[set]; }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && isFunction(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes, ctx); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // IE doesn't make error fields non-enumerable // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { return formatError(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } exports.isArray = isArray; function isBoolean(arg) { return typeof arg === 'boolean'; } exports.isBoolean = isBoolean; function isNull(arg) { return arg === null; } exports.isNull = isNull; function isNullOrUndefined(arg) { return arg == null; } exports.isNullOrUndefined = isNullOrUndefined; function isNumber(arg) { return typeof arg === 'number'; } exports.isNumber = isNumber; function isString(arg) { return typeof arg === 'string'; } exports.isString = isString; function isSymbol(arg) { return typeof arg === 'symbol'; } exports.isSymbol = isSymbol; function isUndefined(arg) { return arg === void 0; } exports.isUndefined = isUndefined; function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isObject(arg) { return typeof arg === 'object' && arg !== null; } exports.isObject = isObject; function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error); } exports.isError = isError; function isFunction(arg) { return typeof arg === 'function'; } exports.isFunction = isFunction; function isPrimitive(arg) { return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined'; } exports.isPrimitive = isPrimitive; exports.isBuffer = require('./support/isBuffer'); function objectToString(o) { return Object.prototype.toString.call(o); } function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } // log is just a thin wrapper to console.log that prepends a timestamp exports.log = function() { console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); }; /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = require('inherits'); exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || !isObject(add)) return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./support/isBuffer":123,"_process":122,"inherits":121}],125:[function(require,module,exports){ var bundleFn = arguments[3]; var sources = arguments[4]; var cache = arguments[5]; var stringify = JSON.stringify; module.exports = function (fn) { var keys = []; var wkey; var cacheKeys = Object.keys(cache); for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; if (cache[key].exports === fn) { wkey = key; break; } } if (!wkey) { wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var wcache = {}; for (var i = 0, l = cacheKeys.length; i < l; i++) { var key = cacheKeys[i]; wcache[key] = key; } sources[wkey] = [ Function(['require','module','exports'], '(' + fn + ')(self)'), wcache ]; } var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); var scache = {}; scache[wkey] = wkey; sources[skey] = [ Function(['require'],'require(' + stringify(wkey) + ')(self)'), scache ]; var src = '(' + bundleFn + ')({' + Object.keys(sources).map(function (key) { return stringify(key) + ':[' + sources[key][0] + ',' + stringify(sources[key][1]) + ']' ; }).join(',') + '},{},[' + stringify(skey) + '])' ; var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; return new Worker(URL.createObjectURL( new Blob([src], { type: 'text/javascript' }) )); }; },{}]},{},[22])(22) }); //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyX3NldC5qcyIsImpzL2RhdGEvYnVmZmVyL2NvbGxpc2lvbl9ib3hfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2ZpbGxfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2dseXBoX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9pY29uX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9saW5lX2VsZW1lbnRfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvbGluZV92ZXJ0ZXhfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvb3V0bGluZV9lbGVtZW50c19idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci90cmlhbmdsZV9lbGVtZW50X2J1ZmZlci5qcyIsImpzL2RhdGEvY3JlYXRlX2J1Y2tldC5qcyIsImpzL2RhdGEvZWxlbWVudF9ncm91cHMuanMiLCJqcy9kYXRhL2ZlYXR1cmVfdHJlZS5qcyIsImpzL2RhdGEvZmlsbF9idWNrZXQuanMiLCJqcy9kYXRhL2xpbmVfYnVja2V0LmpzIiwianMvZGF0YS9zeW1ib2xfYnVja2V0LmpzIiwianMvZ2VvL2Nvb3JkaW5hdGUuanMiLCJqcy9nZW8vbGF0X2xuZy5qcyIsImpzL2dlby9sYXRfbG5nX2JvdW5kcy5qcyIsImpzL2dlby90cmFuc2Zvcm0uanMiLCJqcy9saWIvZGVidWd0ZXh0LmpzIiwianMvbWFwYm94LWdsLmpzIiwianMvcmVuZGVyL2RyYXdfYmFja2dyb3VuZC5qcyIsImpzL3JlbmRlci9kcmF3X2NvbGxpc2lvbl9kZWJ1Zy5qcyIsImpzL3JlbmRlci9kcmF3X2RlYnVnLmpzIiwianMvcmVuZGVyL2RyYXdfZmlsbC5qcyIsImpzL3JlbmRlci9kcmF3X2xpbmUuanMiLCJqcy9yZW5kZXIvZHJhd19yYXN0ZXIuanMiLCJqcy9yZW5kZXIvZHJhd19zeW1ib2wuanMiLCJqcy9yZW5kZXIvZHJhd192ZXJ0aWNlcy5qcyIsImpzL3JlbmRlci9mcmFtZV9oaXN0b3J5LmpzIiwianMvcmVuZGVyL2dsX3V0aWwuanMiLCJqcy9yZW5kZXIvbGluZV9hdGxhcy5qcyIsImpzL3JlbmRlci9wYWludGVyLmpzIiwianMvcmVuZGVyL3NoYWRlcnMuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl9zb3VyY2UuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl93cmFwcGVyLmpzIiwianMvc291cmNlL3Jhc3Rlcl90aWxlX3NvdXJjZS5qcyIsImpzL3NvdXJjZS9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdGlsZS5qcyIsImpzL3NvdXJjZS90aWxlX2Nvb3JkLmpzIiwianMvc291cmNlL3RpbGVfcHlyYW1pZC5qcyIsImpzL3NvdXJjZS92ZWN0b3JfdGlsZV9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdmlkZW9fc291cmNlLmpzIiwianMvc291cmNlL3dvcmtlci5qcyIsImpzL3NvdXJjZS93b3JrZXJfdGlsZS5qcyIsImpzL3N0eWxlL2FuaW1hdGlvbl9sb29wLmpzIiwianMvc3R5bGUvaW1hZ2Vfc3ByaXRlLmpzIiwianMvc3R5bGUvbGF5b3V0X3Byb3BlcnRpZXMuanMiLCJqcy9zdHlsZS9wYWludF9wcm9wZXJ0aWVzLmpzIiwianMvc3R5bGUvcmVmZXJlbmNlLmpzIiwianMvc3R5bGUvc3R5bGUuanMiLCJqcy9zdHlsZS9zdHlsZV9jb25zdGFudC5qcyIsImpzL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uLmpzIiwianMvc3R5bGUvc3R5bGVfZGVjbGFyYXRpb25fc2V0LmpzIiwianMvc3R5bGUvc3R5bGVfbGF5ZXIuanMiLCJqcy9zdHlsZS9zdHlsZV90cmFuc2l0aW9uLmpzIiwianMvc3ltYm9sL2FuY2hvci5qcyIsImpzL3N5bWJvbC9iaW5fcGFjay5qcyIsImpzL3N5bWJvbC9jaGVja19tYXhfYW5nbGUuanMiLCJqcy9zeW1ib2wvY2xpcF9saW5lLmpzIiwianMvc3ltYm9sL2NvbGxpc2lvbl9ib3guanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX2ZlYXR1cmUuanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX3RpbGUuanMiLCJqcy9zeW1ib2wvZ2V0X2FuY2hvcnMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfYXRsYXMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfc291cmNlLmpzIiwianMvc3ltYm9sL21lcmdlbGluZXMuanMiLCJqcy9zeW1ib2wvcXVhZHMuanMiLCJqcy9zeW1ib2wvcmVzb2x2ZV9pY29ucy5qcyIsImpzL3N5bWJvbC9yZXNvbHZlX3RleHQuanMiLCJqcy9zeW1ib2wvc2hhcGluZy5qcyIsImpzL3N5bWJvbC9zcHJpdGVfYXRsYXMuanMiLCJqcy91aS9jYW1lcmEuanMiLCJqcy91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzIiwianMvdWkvY29udHJvbC9jb250cm9sLmpzIiwianMvdWkvY29udHJvbC9uYXZpZ2F0aW9uLmpzIiwianMvdWkvaGFuZGxlcnMuanMiLCJqcy91aS9oYXNoLmpzIiwianMvdWkvaW50ZXJhY3Rpb24uanMiLCJqcy91aS9tYXAuanMiLCJqcy91aS9wb3B1cC5qcyIsImpzL3V0aWwvYWN0b3IuanMiLCJqcy91dGlsL2Jyb3dzZXIvYWpheC5qcyIsImpzL3V0aWwvYnJvd3Nlci9icm93c2VyLmpzIiwianMvdXRpbC9icm93c2VyL2NhbnZhcy5qcyIsImpzL3V0aWwvYnJvd3Nlci9kaXNwYXRjaGVyLmpzIiwianMvdXRpbC9icm93c2VyL2RvbS5qcyIsImpzL3V0aWwvY29uZmlnLmpzIiwianMvdXRpbC9ldmVudGVkLmpzIiwianMvdXRpbC9nbHlwaHMuanMiLCJqcy91dGlsL2ludGVycG9sYXRlLmpzIiwianMvdXRpbC9tYXBib3guanMiLCJqcy91dGlsL21ydV9jYWNoZS5qcyIsImpzL3V0aWwvdG9rZW4uanMiLCJqcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvY3NzY29sb3JwYXJzZXIvY3NzY29sb3JwYXJzZXIuanMiLCJub2RlX21vZHVsZXMvZmVhdHVyZS1maWx0ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2VvanNvbi12dC9zcmMvY2xpcC5qcyIsIm5vZGVfbW9kdWxlcy9nZW9qc29uLXZ0L3NyYy9jb252ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3NpbXBsaWZ5LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3RpbGUuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0cml4L2Rpc3QvZ2wtbWF0cml4LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1mdW5jdGlvbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9saWIvdmFsaWRhdGUvbGF0ZXN0LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1zdHlsZS1zcGVjL2xpYi92YWxpZGF0ZS9wYXJzZWQuanMiLCJub2RlX21vZHVsZXMvbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9yZWZlcmVuY2UvdjcuanNvbiIsIm5vZGVfbW9kdWxlcy9wYmYvYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3BiZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYmYvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcG9pbnQtZ2VvbWV0cnkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmJ1c2gvcmJ1c2guanMiLCJub2RlX21vZHVsZXMvcmVzb2x2ZS11cmwvcmVzb2x2ZS11cmwuanMiLCJub2RlX21vZHVsZXMvdW5pdGJlemllci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZS5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZWZlYXR1cmUuanMiLCJub2RlX21vZHVsZXMvdmVjdG9yLXRpbGUvbGliL3ZlY3RvcnRpbGVsYXllci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvd2Vid29ya2lmeS9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzb0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxdUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9UQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4cElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQy9KQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzFrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIndXNlIHN0cmljdCc7XG5cbi8vIGEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIGEgc2luZ2xlIGFycmF5YnVmZmVyXG5cbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyO1xuXG5mdW5jdGlvbiBCdWZmZXIoYnVmZmVyKSB7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgdGhpcy5hcnJheSA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmRlZmF1bHRMZW5ndGgpO1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGVmYXVsdExlbmd0aDtcbiAgICAgICAgdGhpcy5zZXR1cFZpZXdzKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBvbmx5IHJlY3JlYXRlIGJ1ZmZlcnMgYWZ0ZXIgcmVjZWl2aW5nIHRoZW0gZnJvbSB3b3JrZXJzIGZvciBiaW5kaW5nIHRvIGdsLFxuICAgICAgICAvLyBzbyB3ZSBvbmx5IG5lZWQgdGhlc2UgMiBwcm9wZXJ0aWVzXG4gICAgICAgIHRoaXMuYXJyYXkgPSBidWZmZXIuYXJyYXk7XG4gICAgICAgIHRoaXMucG9zID0gYnVmZmVyLnBvcztcbiAgICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUgPSB7XG4gICAgcG9zOiAwLFxuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBpbiBvbmUgaXRlbVxuICAgIGRlZmF1bHRMZW5ndGg6IDgxOTIsIC8vIGluaXRpYWwgYnVmZmVyIHNpemVcbiAgICBhcnJheVR5cGU6ICdBUlJBWV9CVUZGRVInLCAvLyBnbCBidWZmZXIgdHlwZVxuXG4gICAgZ2V0IGluZGV4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3MgLyB0aGlzLml0ZW1TaXplO1xuICAgIH0sXG5cbiAgICBzZXR1cFZpZXdzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gc2V0IHVwIHZpZXdzIGZvciBlYWNoIHR5cGUgdG8gYWRkIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzIHRvIHRoZSBzYW1lIGJ1ZmZlclxuICAgICAgICB0aGlzLnVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLmJ5dGVzID0gbmV3IEludDhBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy51c2hvcnRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLnNob3J0cyA9IG5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgIH0sXG5cbiAgICAvLyBiaW5kcyB0aGUgYnVmZmVyIHRvIGEgd2ViZ2wgY29udGV4dFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsKSB7XG4gICAgICAgIHZhciB0eXBlID0gZ2xbdGhpcy5hcnJheVR5cGVdO1xuICAgICAgICBpZiAoIXRoaXMuYnVmZmVyKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wuYmluZEJ1ZmZlcih0eXBlLCB0aGlzLmJ1ZmZlcik7XG4gICAgICAgICAgICBnbC5idWZmZXJEYXRhKHR5cGUsIHRoaXMuYXJyYXkuc2xpY2UoMCwgdGhpcy5wb3MpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgICAgIC8vIGR1bXAgYXJyYXkgYnVmZmVyIG9uY2UgaXQncyBib3VuZCB0byBnbFxuICAgICAgICAgICAgdGhpcy5hcnJheSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC5iaW5kQnVmZmVyKHR5cGUsIHRoaXMuYnVmZmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBkZXN0cm95OiBmdW5jdGlvbihnbCkge1xuICAgICAgICBpZiAodGhpcy5idWZmZXIpIHtcbiAgICAgICAgICAgIGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gaW5jcmVhc2UgdGhlIGJ1ZmZlciBzaXplIGJ5IDUwJSBpZiBhIG5ldyBpdGVtIGRvZXNuJ3QgZml0XG4gICAgcmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoIDwgdGhpcy5wb3MgKyB0aGlzLml0ZW1TaXplKSB7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmxlbmd0aCA8IHRoaXMucG9zICsgdGhpcy5pdGVtU2l6ZSkge1xuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBsZW5ndGggYnkgNTAlIGJ1dCBrZWVwIGl0IGV2ZW5cbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IE1hdGgucm91bmQodGhpcy5sZW5ndGggKiAxLjUgLyAyKSAqIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGFycmF5IGJ1ZmZlcnMgY2FuJ3QgYmUgcmVzaXplZCwgc28gd2UgY3JlYXRlIGEgbmV3IG9uZSBhbmQgcmVzZXQgYWxsIGJ5dGVzIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5QnVmZmVyKHRoaXMubGVuZ3RoKTtcblxuICAgICAgICAgICAgdmFyIHVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICAgICAgdWJ5dGVzLnNldCh0aGlzLnVieXRlcyk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExpbmVWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2xpbmVfdmVydGV4X2J1ZmZlcicpO1xudmFyIExpbmVFbGVtZW50QnVmZmVyID0gcmVxdWlyZSgnLi9saW5lX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgRmlsbFZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vZmlsbF92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgRmlsbEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgT3V0bGluZUVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL291dGxpbmVfZWxlbWVudHNfYnVmZmVyJyk7XG52YXIgR2x5cGhWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2dseXBoX3ZlcnRleF9idWZmZXInKTtcbnZhciBHbHlwaEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgSWNvblZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vaWNvbl92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgSWNvbkVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9jb2xsaXNpb25fYm94X3ZlcnRleF9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihidWZmZXJzZXQpIHtcbiAgICBidWZmZXJzZXQgPSBidWZmZXJzZXQgfHwge307XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2x5cGhWZXJ0ZXg6IG5ldyBHbHlwaFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZ2x5cGhWZXJ0ZXgpLFxuICAgICAgICBnbHlwaEVsZW1lbnQ6IG5ldyBHbHlwaEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb25WZXJ0ZXg6IG5ldyBJY29uVmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5pY29uVmVydGV4KSxcbiAgICAgICAgaWNvbkVsZW1lbnQ6IG5ldyBJY29uRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQuaWNvbkVsZW1lbnQpLFxuICAgICAgICBmaWxsVmVydGV4OiBuZXcgRmlsbFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZmlsbFZlcnRleCksXG4gICAgICAgIGZpbGxFbGVtZW50OiBuZXcgRmlsbEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmZpbGxFbGVtZW50KSxcbiAgICAgICAgb3V0bGluZUVsZW1lbnQ6IG5ldyBPdXRsaW5lRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQub3V0bGluZUVsZW1lbnQpLFxuICAgICAgICBsaW5lVmVydGV4OiBuZXcgTGluZVZlcnRleEJ1ZmZlcihidWZmZXJzZXQubGluZVZlcnRleCksXG4gICAgICAgIGxpbmVFbGVtZW50OiBuZXcgTGluZUVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmxpbmVFbGVtZW50KSxcbiAgICAgICAgY29sbGlzaW9uQm94VmVydGV4OiBuZXcgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5jb2xsaXNpb25Cb3hWZXJ0ZXgpXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5Db2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiAxMiwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIGFkZDogZnVuY3Rpb24ocG9pbnQsIGV4dHJ1ZGUsIG1heFpvb20sIHBsYWNlbWVudFpvb20pIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXg7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSBwb2ludC54O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSBwb2ludC55O1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQoZXh0cnVkZS54KTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChleHRydWRlLnkpO1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSA9IE1hdGguZmxvb3IobWF4Wm9vbSAqIDEwKTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gPSBNYXRoLmZsb29yKHBsYWNlbWVudFpvb20gKiAxMCk7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gRmlsbFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogNCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ID09IDQgYnl0ZXMpXG5cbiAgICBhZGQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSB4O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSB5O1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgZGVmYXVsdExlbmd0aDogMjA0OCAqIDE2LFxuICAgIGl0ZW1TaXplOiAxNixcblxuICAgIGFkZDogZnVuY3Rpb24oeCwgeSwgb3gsIG95LCB0eCwgdHksIG1pbnpvb20sIG1heHpvb20sIGxhYmVsbWluem9vbSkge1xuICAgICAgICB2YXIgcG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICBwb3MyID0gcG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IHg7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAxXSA9IHk7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQob3ggKiA2NCk7IC8vIHVzZSAxLzY0IHBpeGVscyBmb3IgcGxhY2VtZW50XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAzXSA9IE1hdGgucm91bmQob3kgKiA2NCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMVxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSAvKiB0ZXggKi8gPSBNYXRoLmZsb29yKHR4IC8gNCk7XG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDldIC8qIHRleCAqLyA9IE1hdGguZmxvb3IodHkgLyA0KTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTBdIC8qIGxhYmVsbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKGxhYmVsbWluem9vbSkgKiAxMCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMl0gLyogbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKG1pbnpvb20pICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcblxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGExLCA0LCBnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA4KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMiwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgMTIpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2x5cGhWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIEdseXBoVmVydGV4QnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBkZWZhdWx0TGVuZ3RoOiAyMDQ4ICogMTYsXG4gICAgaXRlbVNpemU6IDE2LFxuXG4gICAgYWRkOiBmdW5jdGlvbih4LCB5LCBveCwgb3ksIHR4LCB0eSwgbWluem9vbSwgbWF4em9vbSwgbGFiZWxtaW56b29tKSB7XG4gICAgICAgIHZhciBwb3MgPSB0aGlzLnBvcyxcbiAgICAgICAgICAgIHBvczIgPSBwb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDBdID0geDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0geTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDJdID0gTWF0aC5yb3VuZChveCAqIDY0KTsgLy8gdXNlIDEvNjQgcGl4ZWxzIGZvciBwbGFjZW1lbnRcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChveSAqIDY0KTtcblxuICAgICAgICAvLyBhX2RhdGExXG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDhdIC8qIHRleCAqLyA9IHR4IC8gNDtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gLyogdGV4ICovID0gdHkgLyA0O1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMF0gLyogbGFiZWxtaW56b29tICovID0gTWF0aC5mbG9vcigobGFiZWxtaW56b29tIHx8IDApICogMTApO1xuXG4gICAgICAgIC8vIGFfZGF0YTJcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTJdIC8qIG1pbnpvb20gKi8gPSBNYXRoLmZsb29yKChtaW56b29tIHx8IDApICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSB8fCAyNSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMSwgNCwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgOCk7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YTIsIDIsIGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlLCBzdHJpZGUsIG9mZnNldCArIDEyKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVFbGVtZW50QnVmZmVyO1xuXG5mdW5jdGlvbiBMaW5lRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgaXRlbVNpemU6IDYsIC8vIGJ5dGVzIHBlciB0cmlhbmdsZSAoMyAqIHVuc2lnbmVkIHNob3J0ID09IDYgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDJdID0gYztcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZVZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gTGluZVZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG4vLyBzY2FsZSB0aGUgZXh0cnVzaW9uIHZlY3RvciBzbyB0aGF0IHRoZSBub3JtYWwgbGVuZ3RoIGlzIHRoaXMgdmFsdWUuXG4vLyBjb250YWlucyB0aGUgXCJ0ZXh0dXJlXCIgbm9ybWFscyAoLTEuLjEpLiB0aGlzIGlzIGRpc3RpbmN0IGZyb20gdGhlIGV4dHJ1ZGVcbi8vIG5vcm1hbHMgZm9yIGxpbmUgam9pbnMsIGJlY2F1c2UgdGhlIHgtdmFsdWUgcmVtYWlucyAwIGZvciB0aGUgdGV4dHVyZVxuLy8gbm9ybWFsIGFycmF5LCB3aGlsZSB0aGUgZXh0cnVkZSBub3JtYWwgYWN0dWFsbHkgbW92ZXMgdGhlIHZlcnRleCB0byBjcmVhdGVcbi8vIHRoZSBhY3V0ZS9iZXZlbGxlZCBsaW5lIGpvaW4uXG5MaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZSA9IDYzO1xuXG5MaW5lVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogOCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIC8vIHR4LCB0eSAtIHRleHR1cmUgbm9ybWFsXG4gICAgYWRkOiBmdW5jdGlvbihwb2ludCwgZXh0cnVkZSwgdHgsIHR5LCBsaW5lc29mYXIpIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXgsXG4gICAgICAgICAgICBleHRydWRlU2NhbGUgPSBMaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZTtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IChNYXRoLmZsb29yKHBvaW50LngpICogMikgfCB0eDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0gKE1hdGguZmxvb3IocG9pbnQueSkgKiAyKSB8IHR5O1xuXG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNF0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueCk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNV0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueSk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNl0gPSAobGluZXNvZmFyIHx8IDApIC8gMTI4O1xuICAgICAgICB0aGlzLmJ5dGVzW3BvcyArIDddID0gKGxpbmVzb2ZhciB8fCAwKSAlIDEyODtcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBPdXRsaW5lRWxlbWVudHNCdWZmZXI7XG5cbmZ1bmN0aW9uIE91dGxpbmVFbGVtZW50c0J1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5PdXRsaW5lRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBwZXIgbGluZSAoMiAqIHVuc2lnbmVkIHNob3J0ID09IDQgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyO1xuXG5mdW5jdGlvbiBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cblRyaWFuZ2xlRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA2LCAvLyBieXRlcyBwZXIgdHJpYW5nbGUgKDMgKiB1bnNpZ25lZCBzaG9ydCA9PSA2IGJ5dGVzKVxuICAgIGFycmF5VHlwZTogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcblxuICAgIGFkZDogZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAgICB2YXIgcG9zMiA9IHRoaXMucG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDFdID0gYjtcbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAyXSA9IGM7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCdWNrZXQ7XG5cbnZhciBMaW5lQnVja2V0ID0gcmVxdWlyZSgnLi9saW5lX2J1Y2tldCcpO1xudmFyIEZpbGxCdWNrZXQgPSByZXF1aXJlKCcuL2ZpbGxfYnVja2V0Jyk7XG52YXIgU3ltYm9sQnVja2V0ID0gcmVxdWlyZSgnLi9zeW1ib2xfYnVja2V0Jyk7XG52YXIgTGF5b3V0UHJvcGVydGllcyA9IHJlcXVpcmUoJy4uL3N0eWxlL2xheW91dF9wcm9wZXJ0aWVzJyk7XG52YXIgZmVhdHVyZUZpbHRlciA9IHJlcXVpcmUoJ2ZlYXR1cmUtZmlsdGVyJyk7XG52YXIgU3R5bGVEZWNsYXJhdGlvblNldCA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uX3NldCcpO1xuXG5mdW5jdGlvbiBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgeiwgb3ZlcnNjYWxpbmcsIGNvbGxpc2lvbkRlYnVnKSB7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBTdHlsZURlY2xhcmF0aW9uU2V0KCdsYXlvdXQnLCBsYXllci50eXBlLCBsYXllci5sYXlvdXQsIHt9KS52YWx1ZXMoKSxcbiAgICAgICAgZmFrZVpvb21IaXN0b3J5ID0geyBsYXN0SW50ZWdlclpvb206IEluZmluaXR5LCBsYXN0SW50ZWdlclpvb21UaW1lOiAwLCBsYXN0Wm9vbTogMCB9LFxuICAgICAgICBsYXlvdXQgPSB7fTtcblxuICAgIGZvciAodmFyIGsgaW4gdmFsdWVzKSB7XG4gICAgICAgIGxheW91dFtrXSA9IHZhbHVlc1trXS5jYWxjdWxhdGUoeiwgZmFrZVpvb21IaXN0b3J5KTtcbiAgICB9XG5cbiAgICB2YXIgQnVja2V0Q2xhc3MgPVxuICAgICAgICBsYXllci50eXBlID09PSAnbGluZScgPyBMaW5lQnVja2V0IDpcbiAgICAgICAgbGF5ZXIudHlwZSA9PT0gJ2ZpbGwnID8gRmlsbEJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdzeW1ib2wnID8gU3ltYm9sQnVja2V0IDogbnVsbDtcblxuICAgIHZhciBidWNrZXQgPSBuZXcgQnVja2V0Q2xhc3MoYnVmZmVycywgbmV3IExheW91dFByb3BlcnRpZXNbbGF5ZXIudHlwZV0obGF5b3V0KSwgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpO1xuXG4gICAgYnVja2V0LmlkID0gbGF5ZXIuaWQ7XG4gICAgYnVja2V0LnR5cGUgPSBsYXllci50eXBlO1xuICAgIGJ1Y2tldFsnc291cmNlLWxheWVyJ10gPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgYnVja2V0LmludGVyYWN0aXZlID0gbGF5ZXIuaW50ZXJhY3RpdmU7XG4gICAgYnVja2V0Lm1pblpvb20gPSBsYXllci5taW56b29tO1xuICAgIGJ1Y2tldC5tYXhab29tID0gbGF5ZXIubWF4em9vbTtcbiAgICBidWNrZXQuZmlsdGVyID0gZmVhdHVyZUZpbHRlcihsYXllci5maWx0ZXIpO1xuICAgIGJ1Y2tldC5mZWF0dXJlcyA9IFtdO1xuXG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBFbGVtZW50R3JvdXBzO1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXBzKHZlcnRleEJ1ZmZlciwgZWxlbWVudEJ1ZmZlciwgc2Vjb25kRWxlbWVudEJ1ZmZlcikge1xuXG4gICAgdGhpcy52ZXJ0ZXhCdWZmZXIgPSB2ZXJ0ZXhCdWZmZXI7XG4gICAgdGhpcy5lbGVtZW50QnVmZmVyID0gZWxlbWVudEJ1ZmZlcjtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRCdWZmZXIgPSBzZWNvbmRFbGVtZW50QnVmZmVyO1xuICAgIHRoaXMuZ3JvdXBzID0gW107XG59XG5cbkVsZW1lbnRHcm91cHMucHJvdG90eXBlLm1ha2VSb29tRm9yID0gZnVuY3Rpb24obnVtVmVydGljZXMpIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudCB8fCB0aGlzLmN1cnJlbnQudmVydGV4TGVuZ3RoICsgbnVtVmVydGljZXMgPiA2NTUzNSkge1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuZXcgRWxlbWVudEdyb3VwKHRoaXMudmVydGV4QnVmZmVyLmluZGV4LFxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudEJ1ZmZlciAmJiB0aGlzLmVsZW1lbnRCdWZmZXIuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRFbGVtZW50QnVmZmVyICYmIHRoaXMuc2Vjb25kRWxlbWVudEJ1ZmZlci5pbmRleCk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXAodmVydGV4U3RhcnRJbmRleCwgZWxlbWVudFN0YXJ0SW5kZXgsIHNlY29uZEVsZW1lbnRTdGFydEluZGV4KSB7XG4gICAgLy8gdGhlIG9mZnNldCBpbnRvIHRoZSB2ZXJ0ZXggYnVmZmVyIG9mIHRoZSBmaXJzdCB2ZXJ0ZXggaW4gdGhpcyBncm91cFxuICAgIHRoaXMudmVydGV4U3RhcnRJbmRleCA9IHZlcnRleFN0YXJ0SW5kZXg7XG4gICAgdGhpcy5lbGVtZW50U3RhcnRJbmRleCA9IGVsZW1lbnRTdGFydEluZGV4O1xuICAgIHRoaXMuc2Vjb25kRWxlbWVudFN0YXJ0SW5kZXggPSBzZWNvbmRFbGVtZW50U3RhcnRJbmRleDtcbiAgICB0aGlzLmVsZW1lbnRMZW5ndGggPSAwO1xuICAgIHRoaXMudmVydGV4TGVuZ3RoID0gMDtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRMZW5ndGggPSAwO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmJ1c2ggPSByZXF1aXJlKCdyYnVzaCcpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciB2dCA9IHJlcXVpcmUoJ3ZlY3Rvci10aWxlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZlYXR1cmVUcmVlO1xuXG5mdW5jdGlvbiBGZWF0dXJlVHJlZShjb29yZCwgb3ZlcnNjYWxpbmcpIHtcbiAgICB0aGlzLnggPSBjb29yZC54O1xuICAgIHRoaXMueSA9IGNvb3JkLnk7XG4gICAgdGhpcy56ID0gY29vcmQueiAtIE1hdGgubG9nKG92ZXJzY2FsaW5nKSAvIE1hdGguTE4yO1xuICAgIHRoaXMucnRyZWUgPSByYnVzaCg5KTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufVxuXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24oYmJveCwgbGF5ZXJzLCBmZWF0dXJlKSB7XG4gICAgYmJveC5sYXllcnMgPSBsYXllcnM7XG4gICAgYmJveC5mZWF0dXJlID0gZmVhdHVyZTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZC5wdXNoKGJib3gpO1xufTtcblxuLy8gYnVsayBpbnNlcnQgaW50byB0cmVlXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuX2xvYWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnJ0cmVlLmxvYWQodGhpcy50b0JlSW5zZXJ0ZWQpO1xuICAgIHRoaXMudG9CZUluc2VydGVkID0gW107XG59O1xuXG4vLyBGaW5kcyBmZWF0dXJlcyBpbiB0aGlzIHRpbGUgYXQgYSBwYXJ0aWN1bGFyIHBvc2l0aW9uLlxuRmVhdHVyZVRyZWUucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24oYXJncywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy50b0JlSW5zZXJ0ZWQubGVuZ3RoKSB0aGlzLl9sb2FkKCk7XG5cbiAgICB2YXIgcGFyYW1zID0gYXJncy5wYXJhbXMgfHwge30sXG4gICAgICAgIHJhZGl1cyA9IChwYXJhbXMucmFkaXVzIHx8IDApICogNDA5NiAvIGFyZ3Muc2NhbGUsXG4gICAgICAgIHggPSBhcmdzLngsXG4gICAgICAgIHkgPSBhcmdzLnksXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgdmFyIG1hdGNoaW5nID0gdGhpcy5ydHJlZS5zZWFyY2goWyB4IC0gcmFkaXVzLCB5IC0gcmFkaXVzLCB4ICsgcmFkaXVzLCB5ICsgcmFkaXVzIF0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBtYXRjaGluZ1tpXS5mZWF0dXJlLFxuICAgICAgICAgICAgbGF5ZXJzID0gbWF0Y2hpbmdbaV0ubGF5ZXJzLFxuICAgICAgICAgICAgdHlwZSA9IHZ0LlZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW2ZlYXR1cmUudHlwZV07XG5cbiAgICAgICAgaWYgKHBhcmFtcy4kdHlwZSAmJiB0eXBlICE9PSBwYXJhbXMuJHR5cGUpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgaWYgKCFnZW9tZXRyeUNvbnRhaW5zUG9pbnQoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSwgdHlwZSwgbmV3IFBvaW50KHgsIHkpLCByYWRpdXMpKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIGdlb0pTT04gPSBmZWF0dXJlLnRvR2VvSlNPTih0aGlzLngsIHRoaXMueSwgdGhpcy56KTtcbiAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCBsYXllcnMubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IGxheWVyc1tsXTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5sYXllciAmJiBsYXllciAhPT0gcGFyYW1zLmxheWVyLmlkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICByZXN1bHQucHVzaCh1dGlsLmV4dGVuZCh7bGF5ZXI6IGxheWVyfSwgZ2VvSlNPTikpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0KTtcbn07XG5cbmZ1bmN0aW9uIGdlb21ldHJ5Q29udGFpbnNQb2ludChyaW5ncywgdHlwZSwgcCwgcmFkaXVzKSB7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdQb2ludCcgPyBwb2ludENvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cykgOlxuICAgICAgICAgICB0eXBlID09PSAnTGluZVN0cmluZycgPyBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6XG4gICAgICAgICAgIHR5cGUgPT09ICdQb2x5Z29uJyA/IHBvbHlDb250YWluc1BvaW50KHJpbmdzLCBwKSB8fCBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6IGZhbHNlO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTUwMTcyNS8zMzEzNzkuXG5mdW5jdGlvbiBkaXN0VG9TZWdtZW50U3F1YXJlZChwLCB2LCB3KSB7XG4gICAgdmFyIGwyID0gdi5kaXN0U3FyKHcpO1xuICAgIGlmIChsMiA9PT0gMCkgcmV0dXJuIHAuZGlzdFNxcih2KTtcbiAgICB2YXIgdCA9ICgocC54IC0gdi54KSAqICh3LnggLSB2LngpICsgKHAueSAtIHYueSkgKiAody55IC0gdi55KSkgLyBsMjtcbiAgICBpZiAodCA8IDApIHJldHVybiBwLmRpc3RTcXIodik7XG4gICAgaWYgKHQgPiAxKSByZXR1cm4gcC5kaXN0U3FyKHcpO1xuICAgIHJldHVybiBwLmRpc3RTcXIody5zdWIodikuX211bHQodCkuX2FkZCh2KSk7XG59XG5cbmZ1bmN0aW9uIGxpbmVDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAvLyBGaW5kIGxpbmUgc2VnbWVudHMgdGhhdCBoYXZlIGEgZGlzdGFuY2UgPD0gcmFkaXVzXjIgdG8gcFxuICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlLCB3ZSB0cmVhdCB0aGUgbGluZSBhcyBcImNvbnRhaW5pbmcgcG9pbnQgcFwiLlxuICAgICAgICAgICAgdmFyIHYgPSByaW5nW2ogLSAxXSwgdyA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoZGlzdFRvU2VnbWVudFNxdWFyZWQocCwgdiwgdykgPCByKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIHBvaW50IGluIHBvbHlnb24gcmF5IGNhc3RpbmcgYWxnb3JpdGhtXG5mdW5jdGlvbiBwb2x5Q29udGFpbnNQb2ludChyaW5ncywgcCkge1xuICAgIHZhciBjID0gZmFsc2UsXG4gICAgICAgIHJpbmcsIHAxLCBwMjtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgcmluZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgcmluZyA9IHJpbmdzW2tdO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHJpbmcubGVuZ3RoIC0gMTsgaSA8IHJpbmcubGVuZ3RoOyBqID0gaSsrKSB7XG4gICAgICAgICAgICBwMSA9IHJpbmdbaV07XG4gICAgICAgICAgICBwMiA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoKChwMS55ID4gcC55KSAhPT0gKHAyLnkgPiBwLnkpKSAmJiAocC54IDwgKHAyLnggLSBwMS54KSAqIChwLnkgLSBwMS55KSAvIChwMi55IC0gcDEueSkgKyBwMS54KSkge1xuICAgICAgICAgICAgICAgIGMgPSAhYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gcG9pbnRDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAocmluZ1tqXS5kaXN0U3FyKHApIDw9IHIpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbEJ1Y2tldDtcblxuZnVuY3Rpb24gRmlsbEJ1Y2tldChidWZmZXJzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmZpbGxWZXJ0ZXgsIGJ1ZmZlcnMuZmlsbEVsZW1lbnQsIGJ1ZmZlcnMub3V0bGluZUVsZW1lbnQpO1xufVxuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmZWF0dXJlcyA9IHRoaXMuZmVhdHVyZXM7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xuICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxufTtcblxuRmlsbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmFkZEZpbGwobGluZXNbaV0pO1xuICAgIH1cbn07XG5cbkZpbGxCdWNrZXQucHJvdG90eXBlLmFkZEZpbGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIGlmICh2ZXJ0aWNlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgIC8vY29uc29sZS53YXJuKCdhIGZpbGwgbXVzdCBoYXZlIGF0IGxlYXN0IHRocmVlIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiB2ZXJ0aWNlcyB3ZSdyZSBnb2luZyB0byBwcm9kdWNlIHNvIHRoYXQgd2VcbiAgICAvLyBjYW4gcmVzaXplIHRoZSBidWZmZXIgYmVmb3JlaGFuZCwgb3IgZGV0ZWN0IHdoZXRoZXIgdGhlIGN1cnJlbnQgbGluZVxuICAgIC8vIHdvbid0IGZpdCBpbnRvIHRoZSBidWZmZXIgYW55bW9yZS5cbiAgICAvLyBJbiBvcmRlciB0byBiZSBhYmxlIHRvIHVzZSB0aGUgdmVydGV4IGJ1ZmZlciBmb3IgZHJhd2luZyB0aGUgYW50aWFsaWFzZWRcbiAgICAvLyBvdXRsaW5lcywgd2Ugc2VwYXJhdGUgYWxsIHBvbHlnb24gdmVydGljZXMgd2l0aCBhIGRlZ2VuZXJhdGUgKG91dC1vZi1cbiAgICAvLyB2aWV3cGxhbmUpIHZlcnRleC5cblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG5cbiAgICAvLyBDaGVjayB3aGV0aGVyIHRoaXMgZ2VvbWV0cnkgYnVmZmVyIGNhbiBob2xkIGFsbCB0aGUgcmVxdWlyZWQgdmVydGljZXMuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLm1ha2VSb29tRm9yKGxlbiArIDEpO1xuICAgIHZhciBlbGVtZW50R3JvdXAgPSB0aGlzLmVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciBmaWxsVmVydGV4ID0gdGhpcy5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmFyIGZpbGxFbGVtZW50ID0gdGhpcy5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIHZhciBvdXRsaW5lRWxlbWVudCA9IHRoaXMuYnVmZmVycy5vdXRsaW5lRWxlbWVudDtcblxuICAgIC8vIFdlJ3JlIGdlbmVyYXRpbmcgdHJpYW5nbGUgZmFucywgc28gd2UgYWx3YXlzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IGNvb3JkaW5hdGUgaW4gdGhpcyBwb2x5Z29uLlxuICAgIHZhciBmaXJzdEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4LFxuICAgICAgICBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCwgY3VycmVudFZlcnRleDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4O1xuICAgICAgICBjdXJyZW50VmVydGV4ID0gdmVydGljZXNbaV07XG5cbiAgICAgICAgZmlsbFZlcnRleC5hZGQoY3VycmVudFZlcnRleC54LCBjdXJyZW50VmVydGV4LnkpO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoKys7XG5cbiAgICAgICAgLy8gT25seSBhZGQgdHJpYW5nbGVzIHRoYXQgaGF2ZSBkaXN0aW5jdCB2ZXJ0aWNlcy5cbiAgICAgICAgaWYgKGkgPj0gMiAmJiAoY3VycmVudFZlcnRleC54ICE9PSB2ZXJ0aWNlc1swXS54IHx8IGN1cnJlbnRWZXJ0ZXgueSAhPT0gdmVydGljZXNbMF0ueSkpIHtcbiAgICAgICAgICAgIGZpbGxFbGVtZW50LmFkZChmaXJzdEluZGV4LCBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCk7XG4gICAgICAgICAgICBlbGVtZW50R3JvdXAuZWxlbWVudExlbmd0aCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGkgPj0gMSkge1xuICAgICAgICAgICAgb3V0bGluZUVsZW1lbnQuYWRkKHByZXZJbmRleCwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cC5zZWNvbmRFbGVtZW50TGVuZ3RoKys7XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2SW5kZXggPSBjdXJyZW50SW5kZXg7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZUJ1Y2tldDtcblxuZnVuY3Rpb24gTGluZUJ1Y2tldChidWZmZXJzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmxpbmVWZXJ0ZXgsIGJ1ZmZlcnMubGluZUVsZW1lbnQpO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG59XG5cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaV07XG4gICAgICAgIHRoaXMuYWRkRmVhdHVyZShmZWF0dXJlLmxvYWRHZW9tZXRyeSgpKTtcbiAgICB9XG59O1xuXG5MaW5lQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlID0gZnVuY3Rpb24obGluZXMpIHtcbiAgICB2YXIgbGF5b3V0UHJvcGVydGllcyA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuYWRkTGluZShsaW5lc1tpXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtam9pbiddLFxuICAgICAgICAgICAgbGF5b3V0UHJvcGVydGllc1snbGluZS1jYXAnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtbWl0ZXItbGltaXQnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtcm91bmQtbGltaXQnXSk7XG4gICAgfVxufTtcblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkTGluZSA9IGZ1bmN0aW9uKHZlcnRpY2VzLCBqb2luLCBjYXAsIG1pdGVyTGltaXQsIHJvdW5kTGltaXQpIHtcblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG4gICAgLy8gSWYgdGhlIGxpbmUgaGFzIGR1cGxpY2F0ZSB2ZXJ0aWNlcyBhdCB0aGUgZW5kLCBhZGp1c3QgbGVuZ3RoIHRvIHJlbW92ZSB0aGVtLlxuICAgIHdoaWxlIChsZW4gPiAyICYmIHZlcnRpY2VzW2xlbiAtIDFdLmVxdWFscyh2ZXJ0aWNlc1tsZW4gLSAyXSkpIHtcbiAgICAgICAgbGVuLS07XG4gICAgfVxuXG4gICAgaWYgKHZlcnRpY2VzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgLy9jb25zb2xlLndhcm4oJ2EgbGluZSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoam9pbiA9PT0gJ2JldmVsJykgbWl0ZXJMaW1pdCA9IDEuMDU7XG5cbiAgICB2YXIgZmlyc3RWZXJ0ZXggPSB2ZXJ0aWNlc1swXSxcbiAgICAgICAgbGFzdFZlcnRleCA9IHZlcnRpY2VzW2xlbiAtIDFdLFxuICAgICAgICBjbG9zZWQgPSBmaXJzdFZlcnRleC5lcXVhbHMobGFzdFZlcnRleCk7XG5cbiAgICAvLyB3ZSBjb3VsZCBiZSBtb3JlIHByZWNpc2UsIGJ1dCBpdCB3b3VsZCBvbmx5IHNhdmUgYSBuZWdsaWdpYmxlIGFtb3VudCBvZiBzcGFjZVxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKiA0KTtcblxuICAgIGlmIChsZW4gPT09IDIgJiYgY2xvc2VkKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignYSBsaW5lIG1heSBub3QgaGF2ZSBjb2luY2lkZW50IHBvaW50cycpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGJlZ2luQ2FwID0gY2FwLFxuICAgICAgICBlbmRDYXAgPSBjbG9zZWQgPyAnYnV0dCcgOiBjYXAsXG4gICAgICAgIGZsaXAgPSAxLFxuICAgICAgICBkaXN0YW5jZSA9IDAsXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gdHJ1ZSxcbiAgICAgICAgY3VycmVudFZlcnRleCwgcHJldlZlcnRleCwgbmV4dFZlcnRleCwgcHJldk5vcm1hbCwgbmV4dE5vcm1hbCwgb2Zmc2V0QSwgb2Zmc2V0QjtcblxuICAgIC8vIHRoZSBsYXN0IHRocmVlIHZlcnRpY2VzIGFkZGVkXG4gICAgdGhpcy5lMSA9IHRoaXMuZTIgPSB0aGlzLmUzID0gLTE7XG5cbiAgICBpZiAoY2xvc2VkKSB7XG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tsZW4gLSAyXTtcbiAgICAgICAgbmV4dE5vcm1hbCA9IGZpcnN0VmVydGV4LnN1YihjdXJyZW50VmVydGV4KS5fdW5pdCgpLl9wZXJwKCk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgIG5leHRWZXJ0ZXggPSBjbG9zZWQgJiYgaSA9PT0gbGVuIC0gMSA/XG4gICAgICAgICAgICB2ZXJ0aWNlc1sxXSA6IC8vIGlmIHRoZSBsaW5lIGlzIGNsb3NlZCwgd2UgdHJlYXQgdGhlIGxhc3QgdmVydGV4IGxpa2UgdGhlIGZpcnN0XG4gICAgICAgICAgICB2ZXJ0aWNlc1tpICsgMV07IC8vIGp1c3QgdGhlIG5leHQgdmVydGV4XG5cbiAgICAgICAgLy8gaWYgdHdvIGNvbnNlY3V0aXZlIHZlcnRpY2VzIGV4aXN0LCBza2lwIHRoZSBjdXJyZW50IG9uZVxuICAgICAgICBpZiAobmV4dFZlcnRleCAmJiB2ZXJ0aWNlc1tpXS5lcXVhbHMobmV4dFZlcnRleCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChuZXh0Tm9ybWFsKSBwcmV2Tm9ybWFsID0gbmV4dE5vcm1hbDtcbiAgICAgICAgaWYgKGN1cnJlbnRWZXJ0ZXgpIHByZXZWZXJ0ZXggPSBjdXJyZW50VmVydGV4O1xuXG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tpXTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgaG93IGZhciBhbG9uZyB0aGUgbGluZSB0aGUgY3VycmVudFZlcnRleCBpc1xuICAgICAgICBpZiAocHJldlZlcnRleCkgZGlzdGFuY2UgKz0gY3VycmVudFZlcnRleC5kaXN0KHByZXZWZXJ0ZXgpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbm9ybWFsIHRvd2FyZHMgdGhlIG5leHQgdmVydGV4IGluIHRoaXMgbGluZS4gSW4gY2FzZVxuICAgICAgICAvLyB0aGVyZSBpcyBubyBuZXh0IHZlcnRleCwgcHJldGVuZCB0aGF0IHRoZSBsaW5lIGlzIGNvbnRpbnVpbmcgc3RyYWlnaHQsXG4gICAgICAgIC8vIG1lYW5pbmcgdGhhdCB3ZSBhcmUganVzdCB1c2luZyB0aGUgcHJldmlvdXMgbm9ybWFsLlxuICAgICAgICBuZXh0Tm9ybWFsID0gbmV4dFZlcnRleCA/IG5leHRWZXJ0ZXguc3ViKGN1cnJlbnRWZXJ0ZXgpLl91bml0KCkuX3BlcnAoKSA6IHByZXZOb3JtYWw7XG5cbiAgICAgICAgLy8gSWYgd2Ugc3RpbGwgZG9uJ3QgaGF2ZSBhIHByZXZpb3VzIG5vcm1hbCwgdGhpcyBpcyB0aGUgYmVnaW5uaW5nIG9mIGFcbiAgICAgICAgLy8gbm9uLWNsb3NlZCBsaW5lLCBzbyB3ZSdyZSBkb2luZyBhIHN0cmFpZ2h0IFwiam9pblwiLlxuICAgICAgICBwcmV2Tm9ybWFsID0gcHJldk5vcm1hbCB8fCBuZXh0Tm9ybWFsO1xuXG4gICAgICAgIC8vIERldGVybWluZSB0aGUgbm9ybWFsIG9mIHRoZSBqb2luIGV4dHJ1c2lvbi4gSXQgaXMgdGhlIGFuZ2xlIGJpc2VjdG9yXG4gICAgICAgIC8vIG9mIHRoZSBzZWdtZW50cyBiZXR3ZWVuIHRoZSBwcmV2aW91cyBsaW5lIGFuZCB0aGUgbmV4dCBsaW5lLlxuICAgICAgICB2YXIgam9pbk5vcm1hbCA9IHByZXZOb3JtYWwuYWRkKG5leHROb3JtYWwpLl91bml0KCk7XG5cbiAgICAgICAgLyogIGpvaW5Ob3JtYWwgICAgIHByZXZOb3JtYWxcbiAgICAgICAgICogICAgICAgICAgICAg4oaWICAgICAg4oaRXG4gICAgICAgICAqICAgICAgICAgICAgICAgIC5fX19fX19fXy4gcHJldlZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqIG5leHROb3JtYWwgIOKGkCAgfCAgY3VycmVudFZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqICAgICBuZXh0VmVydGV4ICFcbiAgICAgICAgICpcbiAgICAgICAgICovXG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBsZW5ndGggb2YgdGhlIG1pdGVyICh0aGUgcmF0aW8gb2YgdGhlIG1pdGVyIHRvIHRoZSB3aWR0aCkuXG4gICAgICAgIC8vIEZpbmQgdGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgbmV4dCBhbmQgam9pbiBub3JtYWxzXG4gICAgICAgIC8vIHVzaW5nIGRvdCBwcm9kdWN0LiBUaGUgaW52ZXJzZSBvZiB0aGF0IGlzIHRoZSBtaXRlciBsZW5ndGguXG4gICAgICAgIHZhciBjb3NIYWxmQW5nbGUgPSBqb2luTm9ybWFsLnggKiBuZXh0Tm9ybWFsLnggKyBqb2luTm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnk7XG4gICAgICAgIHZhciBtaXRlckxlbmd0aCA9IDEgLyBjb3NIYWxmQW5nbGU7XG5cbiAgICAgICAgLy8gVGhlIGpvaW4gaWYgYSBtaWRkbGUgdmVydGV4LCBvdGhlcndpc2UgdGhlIGNhcC5cbiAgICAgICAgdmFyIG1pZGRsZVZlcnRleCA9IHByZXZWZXJ0ZXggJiYgbmV4dFZlcnRleDtcbiAgICAgICAgdmFyIGN1cnJlbnRKb2luID0gbWlkZGxlVmVydGV4ID8gam9pbiA6IG5leHRWZXJ0ZXggPyBiZWdpbkNhcCA6IGVuZENhcDtcblxuICAgICAgICBpZiAobWlkZGxlVmVydGV4ICYmIGN1cnJlbnRKb2luID09PSAncm91bmQnICYmIG1pdGVyTGVuZ3RoIDwgcm91bmRMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInICYmIG1pdGVyTGVuZ3RoID4gbWl0ZXJMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnYmV2ZWwnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBUaGUgbWF4aW11bSBleHRydWRlIGxlbmd0aCBpcyAxMjggLyA2MyA9IDIgdGltZXMgdGhlIHdpZHRoIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICAvLyBzbyBpZiBtaXRlckxlbmd0aCA+PSAyIHdlIG5lZWQgdG8gZHJhdyBhIGRpZmZlcmVudCB0eXBlIG9mIGJldmVsIHdoZXJlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoID4gMikgY3VycmVudEpvaW4gPSAnZmxpcGJldmVsJztcblxuICAgICAgICAgICAgLy8gSWYgdGhlIG1pdGVyTGVuZ3RoIGlzIHJlYWxseSBzbWFsbCBhbmQgdGhlIGxpbmUgYmV2ZWwgd291bGRuJ3QgYmUgdmlzaWJsZSxcbiAgICAgICAgICAgIC8vIGp1c3QgZHJhdyBhIG1pdGVyIGpvaW4gdG8gc2F2ZSBhIHRyaWFuZ2xlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoIDwgbWl0ZXJMaW1pdCkgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInKSB7XG4gICAgICAgICAgICBqb2luTm9ybWFsLl9tdWx0KG1pdGVyTGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgam9pbk5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdmbGlwYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBtaXRlciBpcyB0b28gYmlnLCBmbGlwIHRoZSBkaXJlY3Rpb24gdG8gbWFrZSBhIGJldmVsZWQgam9pblxuXG4gICAgICAgICAgICBpZiAobWl0ZXJMZW5ndGggPiAxMDApIHtcbiAgICAgICAgICAgICAgICAvLyBBbG1vc3QgcGFyYWxsZWwgbGluZXNcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsID0gbmV4dE5vcm1hbC5jbG9uZSgpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBwcmV2Tm9ybWFsLnggKiBuZXh0Tm9ybWFsLnkgLSBwcmV2Tm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnggPiAwID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgIHZhciBiZXZlbExlbmd0aCA9IG1pdGVyTGVuZ3RoICogcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkubWFnKCkgLyBwcmV2Tm9ybWFsLnN1YihuZXh0Tm9ybWFsKS5tYWcoKTtcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsLl9wZXJwKCkuX211bHQoYmV2ZWxMZW5ndGggKiBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBqb2luTm9ybWFsLCAwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICBmbGlwID0gLWZsaXA7XG5cbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Sm9pbiA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgdmFyIGRpciA9IHByZXZOb3JtYWwueCAqIG5leHROb3JtYWwueSAtIHByZXZOb3JtYWwueSAqIG5leHROb3JtYWwueDtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAtTWF0aC5zcXJ0KG1pdGVyTGVuZ3RoICogbWl0ZXJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGlmIChmbGlwICogZGlyID4gMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJldmVsXG4gICAgICAgICAgICBpZiAoIXN0YXJ0T2ZMaW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCBvZmZzZXRBLCBvZmZzZXRCLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC1vZmZzZXRBLCAtb2Zmc2V0QiwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdidXR0Jykge1xuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJ1dHRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIHByZXZOb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RhcnQgbmV4dCBzZWdtZW50IHdpdGggYSBidXR0XG4gICAgICAgICAgICBpZiAobmV4dFZlcnRleCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbmV4dE5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdzcXVhcmUnKSB7XG5cbiAgICAgICAgICAgIGlmICghc3RhcnRPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAvLyBDbG9zZSBwcmV2aW91cyBzZWdtZW50IHdpdGggYSBzcXVhcmUgY2FwXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgc2VnbWVudCBpcyBkb25lLiBVbnNldCB2ZXJ0aWNlcyB0byBkaXNjb25uZWN0IHNlZ21lbnRzLlxuICAgICAgICAgICAgICAgIHRoaXMuZTEgPSB0aGlzLmUyID0gLTE7XG4gICAgICAgICAgICAgICAgZmxpcCA9IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdyb3VuZCcpIHtcblxuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBidXR0XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAwLCAwLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgcm91bmQgY2FwIG9yIGxpbmVqb2luIGF0IGVuZCBvZiBzZWdtZW50XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSBzZWdtZW50IGlzIGRvbmUuIFVuc2V0IHZlcnRpY2VzIHRvIGRpc2Nvbm5lY3Qgc2VnbWVudHMuXG4gICAgICAgICAgICAgICAgdGhpcy5lMSA9IHRoaXMuZTIgPSAtMTtcbiAgICAgICAgICAgICAgICBmbGlwID0gMTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChiZWdpbkNhcCA9PT0gJ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIC8vIEFkZCByb3VuZCBjYXAgYmVmb3JlIGZpcnN0IHNlZ21lbnRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudCB3aXRoIGEgYnV0dFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gZmFsc2U7XG4gICAgfVxuXG5cbn07XG5cbi8qKlxuICogQWRkIHR3byB2ZXJ0aWNlcyB0byB0aGUgYnVmZmVycy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3VycmVudFZlcnRleCB0aGUgbGluZSB2ZXJ0ZXggdG8gYWRkIGJ1ZmZlciB2ZXJ0aWNlcyBmb3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBmbGlwIC0xIGlmIHRoZSB2ZXJ0aWNlcyBzaG91bGQgYmUgZmxpcHBlZCwgMSBvdGhlcndpc2VcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZSB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgYmVnZ2luaW5nIG9mIHRoZSBsaW5lIHRvIHRoZSB2ZXJ0ZXhcbiAqIEBwYXJhbSB7TnVtYmVyfSBlbmRMZWZ0IGV4dHJ1ZGUgdG8gc2hpZnQgdGhlIGxlZnQgdmVydGV4IGFsb25nIHRoZSBsaW5lXG4gKiBAcGFyYW0ge051bWJlcn0gZW5kUmlnaHQgZXh0cnVkZSB0byBzaGlmdCB0aGUgbGVmdCB2ZXJ0ZXggYWxvbmcgdGhlIGxpbmVcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gcm91bmQgd2hldGhlciB0aGlzIGlzIGEgcm91bmQgY2FwXG4gKi9cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEN1cnJlbnRWZXJ0ZXggPSBmdW5jdGlvbihjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbm9ybWFsLCBlbmRMZWZ0LCBlbmRSaWdodCwgcm91bmQpIHtcbiAgICB2YXIgdHggPSByb3VuZCA/IDEgOiAwO1xuICAgIHZhciBleHRydWRlO1xuXG4gICAgdmFyIGxpbmVWZXJ0ZXggPSB0aGlzLmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2YXIgbGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMubGluZUVsZW1lbnQ7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IHRoaXMuZWxlbWVudEdyb3Vwcy5jdXJyZW50O1xuICAgIHZhciB2ZXJ0ZXhTdGFydEluZGV4ID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQudmVydGV4U3RhcnRJbmRleDtcblxuICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdChmbGlwKTtcbiAgICBpZiAoZW5kTGVmdCkgZXh0cnVkZS5fc3ViKG5vcm1hbC5wZXJwKCkuX211bHQoZW5kTGVmdCkpO1xuICAgIHRoaXMuZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMCwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICBpZiAodGhpcy5lMSA+PSAwICYmIHRoaXMuZTIgPj0gMCkge1xuICAgICAgICBsaW5lRWxlbWVudC5hZGQodGhpcy5lMSwgdGhpcy5lMiwgdGhpcy5lMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoKys7XG4gICAgfVxuICAgIHRoaXMuZTEgPSB0aGlzLmUyO1xuICAgIHRoaXMuZTIgPSB0aGlzLmUzO1xuXG4gICAgZXh0cnVkZSA9IG5vcm1hbC5tdWx0KC1mbGlwKTtcbiAgICBpZiAoZW5kUmlnaHQpIGV4dHJ1ZGUuX3N1Yihub3JtYWwucGVycCgpLl9tdWx0KGVuZFJpZ2h0KSk7XG4gICAgdGhpcy5lMyA9IGxpbmVWZXJ0ZXguYWRkKGN1cnJlbnRWZXJ0ZXgsIGV4dHJ1ZGUsIHR4LCAxLCBkaXN0YW5jZSkgLSB2ZXJ0ZXhTdGFydEluZGV4O1xuICAgIGlmICh0aGlzLmUxID49IDAgJiYgdGhpcy5lMiA+PSAwKSB7XG4gICAgICAgIGxpbmVFbGVtZW50LmFkZCh0aGlzLmUxLCB0aGlzLmUyLCB0aGlzLmUzKTtcbiAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICB9XG4gICAgdGhpcy5lMSA9IHRoaXMuZTI7XG4gICAgdGhpcy5lMiA9IHRoaXMuZTM7XG5cbiAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudF9ncm91cHMnKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG52YXIgZ2V0QW5jaG9ycyA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nZXRfYW5jaG9ycycpO1xudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG52YXIgUXVhZHMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcXVhZHMnKTtcbnZhciBTaGFwaW5nID0gcmVxdWlyZSgnLi4vc3ltYm9sL3NoYXBpbmcnKTtcbnZhciByZXNvbHZlVGV4dCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9yZXNvbHZlX3RleHQnKTtcbnZhciByZXNvbHZlSWNvbnMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcmVzb2x2ZV9pY29ucycpO1xudmFyIG1lcmdlTGluZXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvbWVyZ2VsaW5lcycpO1xudmFyIHNoYXBlVGV4dCA9IFNoYXBpbmcuc2hhcGVUZXh0O1xudmFyIHNoYXBlSWNvbiA9IFNoYXBpbmcuc2hhcGVJY29uO1xudmFyIGdldEdseXBoUXVhZHMgPSBRdWFkcy5nZXRHbHlwaFF1YWRzO1xudmFyIGdldEljb25RdWFkcyA9IFF1YWRzLmdldEljb25RdWFkcztcbnZhciBjbGlwTGluZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9jbGlwX2xpbmUnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbnZhciBDb2xsaXNpb25GZWF0dXJlID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl9mZWF0dXJlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU3ltYm9sQnVja2V0O1xuXG5mdW5jdGlvbiBTeW1ib2xCdWNrZXQoYnVmZmVycywgbGF5b3V0UHJvcGVydGllcywgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpIHtcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG4gICAgdGhpcy5jb2xsaXNpb24gPSBjb2xsaXNpb247XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IG92ZXJzY2FsaW5nO1xuICAgIHRoaXMuY29sbGlzaW9uRGVidWcgPSBjb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3ltYm9sSW5zdGFuY2VzID0gW107XG5cbn1cblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gdGhpcy50ZXh0RmVhdHVyZXM7XG5cbiAgICB2YXIgaG9yaXpvbnRhbEFsaWduID0gMC41LFxuICAgICAgICB2ZXJ0aWNhbEFsaWduID0gMC41O1xuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBjYXNlICd0b3AtcmlnaHQnOlxuICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgICAgaG9yaXpvbnRhbEFsaWduID0gMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICBjYXNlICdib3R0b20tbGVmdCc6XG4gICAgICAgICAgICBob3Jpem9udGFsQWxpZ24gPSAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgY2FzZSAnYm90dG9tLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgY2FzZSAndG9wLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDA7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIganVzdGlmeSA9IGxheW91dFsndGV4dC1qdXN0aWZ5J10gPT09ICdyaWdodCcgPyAxIDpcbiAgICAgICAgbGF5b3V0Wyd0ZXh0LWp1c3RpZnknXSA9PT0gJ2xlZnQnID8gMCA6XG4gICAgICAgIDAuNTtcblxuICAgIHZhciBvbmVFbSA9IDI0O1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gbGF5b3V0Wyd0ZXh0LWxpbmUtaGVpZ2h0J10gKiBvbmVFbTtcbiAgICB2YXIgbWF4V2lkdGggPSBsYXlvdXRbJ3N5bWJvbC1wbGFjZW1lbnQnXSAhPT0gJ2xpbmUnID8gbGF5b3V0Wyd0ZXh0LW1heC13aWR0aCddICogb25lRW0gOiAwO1xuICAgIHZhciBzcGFjaW5nID0gbGF5b3V0Wyd0ZXh0LWxldHRlci1zcGFjaW5nJ10gKiBvbmVFbTtcbiAgICB2YXIgdGV4dE9mZnNldCA9IFtsYXlvdXRbJ3RleHQtb2Zmc2V0J11bMF0gKiBvbmVFbSwgbGF5b3V0Wyd0ZXh0LW9mZnNldCddWzFdICogb25lRW1dO1xuICAgIHZhciBmb250c3RhY2sgPSBsYXlvdXRbJ3RleHQtZm9udCddO1xuXG4gICAgdmFyIGdlb21ldHJpZXMgPSBbXTtcbiAgICBmb3IgKHZhciBnID0gMDsgZyA8IGZlYXR1cmVzLmxlbmd0aDsgZysrKSB7XG4gICAgICAgIGdlb21ldHJpZXMucHVzaChmZWF0dXJlc1tnXS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgLy8gTWVyZ2UgYWRqYWNlbnQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IHRvIGltcHJvdmUgbGFiZWxsaW5nLlxuICAgICAgICAvLyBJdCdzIGJldHRlciB0byBwbGFjZSBsYWJlbHMgb24gb25lIGxvbmcgbGluZSB0aGFuIG9uIG1hbnkgc2hvcnQgc2VnbWVudHMuXG4gICAgICAgIHZhciBtZXJnZWQgPSBtZXJnZUxpbmVzKGZlYXR1cmVzLCB0ZXh0RmVhdHVyZXMsIGdlb21ldHJpZXMpO1xuXG4gICAgICAgIGdlb21ldHJpZXMgPSBtZXJnZWQuZ2VvbWV0cmllcztcbiAgICAgICAgZmVhdHVyZXMgPSBtZXJnZWQuZmVhdHVyZXM7XG4gICAgICAgIHRleHRGZWF0dXJlcyA9IG1lcmdlZC50ZXh0RmVhdHVyZXM7XG4gICAgfVxuXG4gICAgdmFyIHNoYXBlZFRleHQsIHNoYXBlZEljb247XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGlmICghZ2VvbWV0cmllc1trXSkgY29udGludWU7XG5cbiAgICAgICAgaWYgKHRleHRGZWF0dXJlc1trXSkge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IHNoYXBlVGV4dCh0ZXh0RmVhdHVyZXNba10sIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10sIG1heFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBsaW5lSGVpZ2h0LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIGp1c3RpZnksIHNwYWNpbmcsIHRleHRPZmZzZXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5b3V0WydpY29uLWltYWdlJ10pIHtcbiAgICAgICAgICAgIHZhciBpY29uTmFtZSA9IHJlc29sdmVUb2tlbnMoZmVhdHVyZXNba10ucHJvcGVydGllcywgbGF5b3V0WydpY29uLWltYWdlJ10pO1xuICAgICAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pY29uc1tpY29uTmFtZV07XG4gICAgICAgICAgICBzaGFwZWRJY29uID0gc2hhcGVJY29uKGltYWdlLCBsYXlvdXQpO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZGZJY29ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2RmSWNvbnMgPSBpbWFnZS5zZGY7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNkZkljb25zICE9PSBpbWFnZS5zZGYpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdTdHlsZSBzaGVldCB3YXJuaW5nOiBDYW5ub3QgbWl4IFNERiBhbmQgbm9uLVNERiBpY29ucyBpbiBvbmUgYnVja2V0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkSWNvbiA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hhcGVkVGV4dCB8fCBzaGFwZWRJY29uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZ2VvbWV0cmllc1trXSwgc2hhcGVkVGV4dCwgc2hhcGVkSWNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnBsYWNlRmVhdHVyZXModGhpcy5idWZmZXJzLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICB2YXIgZ2x5cGhTaXplID0gMjQ7XG5cbiAgICB2YXIgZm9udFNjYWxlID0gbGF5b3V0Wyd0ZXh0LW1heC1zaXplJ10gLyBnbHlwaFNpemUsXG4gICAgICAgIHRleHRCb3hTY2FsZSA9IGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyAqIGZvbnRTY2FsZSxcbiAgICAgICAgaWNvbkJveFNjYWxlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydpY29uLW1heC1zaXplJ10sXG4gICAgICAgIHN5bWJvbE1pbkRpc3RhbmNlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydzeW1ib2wtbWluLWRpc3RhbmNlJ10sXG4gICAgICAgIGF2b2lkRWRnZXMgPSBsYXlvdXRbJ3N5bWJvbC1hdm9pZC1lZGdlcyddLFxuICAgICAgICB0ZXh0UGFkZGluZyA9IGxheW91dFsndGV4dC1wYWRkaW5nJ10gKiBjb2xsaXNpb24udGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIGljb25QYWRkaW5nID0gbGF5b3V0WydpY29uLXBhZGRpbmcnXSAqIGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdGV4dE1heEFuZ2xlID0gbGF5b3V0Wyd0ZXh0LW1heC1hbmdsZSddIC8gMTgwICogTWF0aC5QSSxcbiAgICAgICAgdGV4dEFsb25nTGluZSA9IGxheW91dFsndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgaWNvbkFsb25nTGluZSA9IGxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICAgICAgbGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddO1xuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgbGluZXMgPSBjbGlwTGluZShsaW5lcywgMCwgMCwgNDA5NiwgNDA5Nik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYW5jaG9yIHBvaW50cyBhcm91bmQgd2hpY2ggeW91IHdhbnQgdG8gcGxhY2UgbGFiZWxzXG4gICAgICAgIHZhciBhbmNob3JzID0gbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyA/XG4gICAgICAgICAgICBnZXRBbmNob3JzKGxpbmUsIHN5bWJvbE1pbkRpc3RhbmNlLCB0ZXh0TWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgdGV4dEJveFNjYWxlLCB0aGlzLm92ZXJzY2FsaW5nKSA6XG4gICAgICAgICAgICBbIG5ldyBBbmNob3IobGluZVswXS54LCBsaW5lWzBdLnksIDApIF07XG5cbiAgICAgICAgLy8gRm9yIGVhY2ggcG90ZW50aWFsIGxhYmVsLCBjcmVhdGUgdGhlIHBsYWNlbWVudCBmZWF0dXJlcyB1c2VkIHRvIGNoZWNrIGZvciBjb2xsaXNpb25zLCBhbmQgdGhlIHF1YWRzIHVzZSBmb3IgcmVuZGVyaW5nLlxuICAgICAgICBmb3IgKHZhciBqID0gMCwgbGVuID0gYW5jaG9ycy5sZW5ndGg7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgdmFyIGFuY2hvciA9IGFuY2hvcnNbal07XG5cbiAgICAgICAgICAgIHZhciBpbnNpZGUgPSAhKGFuY2hvci54IDwgMCB8fCBhbmNob3IueCA+IDQwOTYgfHwgYW5jaG9yLnkgPCAwIHx8IGFuY2hvci55ID4gNDA5Nik7XG5cbiAgICAgICAgICAgIGlmIChhdm9pZEVkZ2VzICYmICFpbnNpZGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBOb3JtYWxseSBzeW1ib2wgbGF5ZXJzIGFyZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBPbmx5IHN5bWJvbHNcbiAgICAgICAgICAgIC8vIHdpdGggdGhlaXIgYW5jaG9ycyB3aXRoaW4gdGhlIHRpbGUgYm91bmRhcmllcyBhcmUgYWRkZWQgdG8gdGhlIGJ1ZmZlcnNcbiAgICAgICAgICAgIC8vIHRvIHByZXZlbnQgc3ltYm9scyBmcm9tIGJlaW5nIGRyYXduIHR3aWNlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFN5bWJvbHMgaW4gbGF5ZXJzIHdpdGggb3ZlcmxhcCBhcmUgc29ydGVkIGluIHRoZSB5IGRpcmVjdGlvbiBzbyB0aGF0XG4gICAgICAgICAgICAvLyBzeW1ib2xzIGxvd2VyIG9uIHRoZSBjYW52YXMgYXJlIGRyYXduIG9uIHRvcCBvZiBzeW1ib2xzIG5lYXIgdGhlIHRvcC5cbiAgICAgICAgICAgIC8vIFRvIHByZXNlcnZlIHRoaXMgb3JkZXIgYWNyb3NzIHRpbGUgYm91bmRhcmllcyB0aGVzZSBzeW1ib2xzIGNhbid0XG4gICAgICAgICAgICAvLyBiZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBJbnN0ZWFkIHRoZXkgbmVlZCB0byBiZSBpbmNsdWRlZCBpblxuICAgICAgICAgICAgLy8gdGhlIGJ1ZmZlcnMgZm9yIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgdG8gdGlsZSBib3VuZGFyaWVzIGF0IGRyYXcgdGltZS5cbiAgICAgICAgICAgIHZhciBhZGRUb0J1ZmZlcnMgPSBpbnNpZGUgfHwgbWF5T3ZlcmxhcDtcblxuICAgICAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMucHVzaChuZXcgU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLnBsYWNlRmVhdHVyZXMgPSBmdW5jdGlvbihidWZmZXJzLCBjb2xsaXNpb25EZWJ1Zykge1xuXG4gICAgLy8gQ2FsY3VsYXRlIHdoaWNoIGxhYmVscyBjYW4gYmUgc2hvd24gYW5kIHdoZW4gdGhleSBjYW4gYmUgc2hvd24gYW5kXG4gICAgLy8gY3JlYXRlIHRoZSBidWZlcnMgdXNlZCBmb3IgcmVuZGVyaW5nLlxuXG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcblxuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGhpcy5lbGVtZW50R3JvdXBzID0ge1xuICAgICAgICB0ZXh0OiBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmdseXBoVmVydGV4LCBidWZmZXJzLmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb246IG5ldyBFbGVtZW50R3JvdXBzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCksXG4gICAgICAgIHNkZkljb25zOiB0aGlzLnNkZkljb25zXG4gICAgfTtcblxuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGNvbGxpc2lvbiA9IHRoaXMuY29sbGlzaW9uO1xuICAgIHZhciBtYXhTY2FsZSA9IHRoaXMuY29sbGlzaW9uLm1heFNjYWxlO1xuXG4gICAgdmFyIHRleHRBbG9uZ0xpbmUgPSBsYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG4gICAgdmFyIGljb25BbG9uZ0xpbmUgPSBsYXlvdXRbJ2ljb24tcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG5cbiAgICB2YXIgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICBsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddIHx8IGxheW91dFsnaWNvbi1pZ25vcmUtcGxhY2VtZW50J107XG5cbiAgICAvLyBTb3J0IHN5bWJvbHMgYnkgdGhlaXIgeSBwb3NpdGlvbiBvbiB0aGUgY2FudmFzIHNvIHRoYXQgdGhleSBsb3dlciBzeW1ib2xzXG4gICAgLy8gYXJlIGRyYXduIG9uIHRvcCBvZiBoaWdoZXIgc3ltYm9scy5cbiAgICAvLyBEb24ndCBzb3J0IHN5bWJvbHMgdGhhdCB3b24ndCBvdmVybGFwIGJlY2F1c2UgaXQgaXNuJ3QgbmVjZXNzYXJ5IGFuZFxuICAgIC8vIGJlY2F1c2UgaXQgY2F1c2VzIG1vcmUgbGFiZWxzIHRvIHBvcCBpbiBhbmQgb3V0IHdoZW4gcm90YXRpbmcuXG4gICAgaWYgKG1heU92ZXJsYXApIHtcbiAgICAgICAgdmFyIGFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGU7XG4gICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICBjb3MgPSBNYXRoLmNvcyhhbmdsZSk7XG5cbiAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICB2YXIgYVJvdGF0ZWQgPSBzaW4gKiBhLnggKyBjb3MgKiBhLnk7XG4gICAgICAgICAgICB2YXIgYlJvdGF0ZWQgPSBzaW4gKiBiLnggKyBjb3MgKiBiLnk7XG4gICAgICAgICAgICByZXR1cm4gYlJvdGF0ZWQgLSBhUm90YXRlZDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgcCA9IDA7IHAgPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IHArKykge1xuICAgICAgICB2YXIgc3ltYm9sSW5zdGFuY2UgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1twXTtcbiAgICAgICAgdmFyIGhhc1RleHQgPSBzeW1ib2xJbnN0YW5jZS5oYXNUZXh0O1xuICAgICAgICB2YXIgaGFzSWNvbiA9IHN5bWJvbEluc3RhbmNlLmhhc0ljb247XG5cbiAgICAgICAgdmFyIGljb25XaXRob3V0VGV4dCA9IGxheW91dFsndGV4dC1vcHRpb25hbCddIHx8ICFoYXNUZXh0LFxuICAgICAgICAgICAgdGV4dFdpdGhvdXRJY29uID0gbGF5b3V0WydpY29uLW9wdGlvbmFsJ10gfHwgIWhhc0ljb247XG5cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNjYWxlcyBhdCB3aGljaCB0aGUgdGV4dCBhbmQgaWNvbiBjYW4gYmUgcGxhY2VkIHdpdGhvdXQgY29sbGlzaW9uLlxuXG4gICAgICAgIHZhciBnbHlwaFNjYWxlID0gaGFzVGV4dCAmJiAhbGF5b3V0Wyd0ZXh0LWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLnRleHRDb2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuICAgICAgICB2YXIgaWNvblNjYWxlID0gaGFzSWNvbiAmJiAhbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLmljb25Db2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuXG4gICAgICAgIC8vIENvbWJpbmUgdGhlIHNjYWxlcyBmb3IgaWNvbnMgYW5kIHRleHQuXG5cbiAgICAgICAgaWYgKCFpY29uV2l0aG91dFRleHQgJiYgIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gZ2x5cGhTY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRleHRXaXRob3V0SWNvbiAmJiBnbHlwaFNjYWxlKSB7XG4gICAgICAgICAgICBnbHlwaFNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfSBlbHNlIGlmICghaWNvbldpdGhvdXRUZXh0ICYmIGljb25TY2FsZSkge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgLy8gSW5zZXJ0IGZpbmFsIHBsYWNlbWVudCBpbnRvIGNvbGxpc2lvbiB0cmVlIGFuZCBhZGQgZ2x5cGhzL2ljb25zIHRvIGJ1ZmZlcnNcblxuICAgICAgICBpZiAoaGFzVGV4dCkge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UudGV4dENvbGxpc2lvbkZlYXR1cmUsIGdseXBoU2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdseXBoU2NhbGUgPD0gbWF4U2NhbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFN5bWJvbHMoYnVmZmVycy5nbHlwaFZlcnRleCwgYnVmZmVycy5nbHlwaEVsZW1lbnQsIGVsZW1lbnRHcm91cHMudGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJvbEluc3RhbmNlLmdseXBoUXVhZHMsIGdseXBoU2NhbGUsIGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXSwgdGV4dEFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzSWNvbikge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UuaWNvbkNvbGxpc2lvbkZlYXR1cmUsIGljb25TY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaWNvblNjYWxlIDw9IG1heFNjYWxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTeW1ib2xzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCwgZWxlbWVudEdyb3Vwcy5pY29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3ltYm9sSW5zdGFuY2UuaWNvblF1YWRzLCBpY29uU2NhbGUsIGxheW91dFsnaWNvbi1rZWVwLXVwcmlnaHQnXSwgaWNvbkFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGlmIChjb2xsaXNpb25EZWJ1ZykgdGhpcy5hZGRUb0RlYnVnQnVmZmVycygpO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRTeW1ib2xzID0gZnVuY3Rpb24odmVydGV4LCBlbGVtZW50LCBlbGVtZW50R3JvdXBzLCBxdWFkcywgc2NhbGUsIGtlZXBVcHJpZ2h0LCBhbG9uZ0xpbmUpIHtcblxuICAgIGVsZW1lbnRHcm91cHMubWFrZVJvb21Gb3IoNCAqIHF1YWRzLmxlbmd0aCk7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IGVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciB6b29tID0gdGhpcy5jb2xsaXNpb24uem9vbTtcbiAgICB2YXIgcGxhY2VtZW50Wm9vbSA9IE1hdGgubWF4KE1hdGgubG9nKHNjYWxlKSAvIE1hdGguTE4yICsgem9vbSwgMCk7XG4gICAgdmFyIHBsYWNlbWVudEFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGUgKyBNYXRoLlBJO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBxdWFkcy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBxdWFkc1trXSxcbiAgICAgICAgICAgIGFuZ2xlID0gc3ltYm9sLmFuZ2xlO1xuXG4gICAgICAgIC8vIGRyb3AgdXBzaWRlIGRvd24gdmVyc2lvbnMgb2YgZ2x5cGhzXG4gICAgICAgIHZhciBhID0gKGFuZ2xlICsgcGxhY2VtZW50QW5nbGUpICUgKE1hdGguUEkgKiAyKTtcbiAgICAgICAgaWYgKGtlZXBVcHJpZ2h0ICYmIGFsb25nTGluZSAmJiAoYSA8PSBNYXRoLlBJIC8gMiB8fCBhID4gTWF0aC5QSSAqIDMgLyAyKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIHRsID0gc3ltYm9sLnRsLFxuICAgICAgICAgICAgdHIgPSBzeW1ib2wudHIsXG4gICAgICAgICAgICBibCA9IHN5bWJvbC5ibCxcbiAgICAgICAgICAgIGJyID0gc3ltYm9sLmJyLFxuICAgICAgICAgICAgdGV4ID0gc3ltYm9sLnRleCxcbiAgICAgICAgICAgIGFuY2hvciA9IHN5bWJvbC5hbmNob3IsXG5cbiAgICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heCh6b29tICsgTWF0aC5sb2coc3ltYm9sLm1pblNjYWxlKSAvIE1hdGguTE4yLCBwbGFjZW1lbnRab29tKSxcbiAgICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbih6b29tICsgTWF0aC5sb2coc3ltYm9sLm1heFNjYWxlKSAvIE1hdGguTE4yLCAyNSk7XG5cbiAgICAgICAgaWYgKG1heFpvb20gPD0gbWluWm9vbSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTG93ZXIgbWluIHpvb20gc28gdGhhdCB3aGlsZSBmYWRpbmcgb3V0IHRoZSBsYWJlbCBpdCBjYW4gYmUgc2hvd24gb3V0c2lkZSBvZiBjb2xsaXNpb24tZnJlZSB6b29tIGxldmVsc1xuICAgICAgICBpZiAobWluWm9vbSA9PT0gcGxhY2VtZW50Wm9vbSkgbWluWm9vbSA9IDA7XG5cbiAgICAgICAgdmFyIHRyaWFuZ2xlSW5kZXggPSB2ZXJ0ZXguaW5kZXggLSBlbGVtZW50R3JvdXAudmVydGV4U3RhcnRJbmRleDtcblxuICAgICAgICB2ZXJ0ZXguYWRkKGFuY2hvci54LCBhbmNob3IueSwgdGwueCwgdGwueSwgdGV4LngsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRyLngsIHRyLnksIHRleC54ICsgdGV4LncsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJsLngsIGJsLnksIHRleC54LCB0ZXgueSArIHRleC5oLCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJyLngsIGJyLnksIHRleC54ICsgdGV4LncsIHRleC55ICsgdGV4LmgsIG1pblpvb20sIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDQ7XG5cbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCwgdHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyKTtcbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyLCB0cmlhbmdsZUluZGV4ICsgMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoICs9IDI7XG4gICAgfVxuXG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmaXJzdGRvbmUgPSBmYWxzZTtcbiAgICB0aGlzLmdldFRleHREZXBlbmRlbmNpZXModGlsZSwgYWN0b3IsIGRvbmUpO1xuICAgIHRoaXMuZ2V0SWNvbkRlcGVuZGVuY2llcyh0aWxlLCBhY3RvciwgZG9uZSk7XG4gICAgZnVuY3Rpb24gZG9uZShlcnIpIHtcbiAgICAgICAgaWYgKGVyciB8fCBmaXJzdGRvbmUpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICBmaXJzdGRvbmUgPSB0cnVlO1xuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuZ2V0SWNvbkRlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmxheW91dFByb3BlcnRpZXNbJ2ljb24taW1hZ2UnXSkge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgICAgICB2YXIgaWNvbnMgPSByZXNvbHZlSWNvbnMoZmVhdHVyZXMsIHRoaXMubGF5b3V0UHJvcGVydGllcyk7XG5cbiAgICAgICAgaWYgKGljb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgYWN0b3Iuc2VuZCgnZ2V0IGljb25zJywgeyBpY29uczogaWNvbnMgfSwgc2V0SWNvbnMuYmluZCh0aGlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRJY29ucyhlcnIsIG5ld2ljb25zKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB0aGlzLmljb25zID0gbmV3aWNvbnM7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5nZXRUZXh0RGVwZW5kZW5jaWVzID0gZnVuY3Rpb24odGlsZSwgYWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgZm9udHN0YWNrID0gdGhpcy5sYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZvbnQnXTtcblxuICAgIHZhciBzdGFja3MgPSB0aGlzLnN0YWNrcyA9IHRpbGUuc3RhY2tzO1xuICAgIGlmIChzdGFja3NbZm9udHN0YWNrXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN0YWNrc1tmb250c3RhY2tdID0ge307XG4gICAgfVxuICAgIHZhciBzdGFjayA9IHN0YWNrc1tmb250c3RhY2tdO1xuXG4gICAgdmFyIGRhdGEgPSByZXNvbHZlVGV4dChmZWF0dXJlcywgdGhpcy5sYXlvdXRQcm9wZXJ0aWVzLCBzdGFjayk7XG4gICAgdGhpcy50ZXh0RmVhdHVyZXMgPSBkYXRhLnRleHRGZWF0dXJlcztcblxuICAgIGFjdG9yLnNlbmQoJ2dldCBnbHlwaHMnLCB7XG4gICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgIGZvbnRzdGFjazogZm9udHN0YWNrLFxuICAgICAgICBjb2RlcG9pbnRzOiBkYXRhLmNvZGVwb2ludHNcbiAgICB9LCBmdW5jdGlvbihlcnIsIG5ld3N0YWNrKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgIGZvciAodmFyIGNvZGVwb2ludCBpbiBuZXdzdGFjaykge1xuICAgICAgICAgICAgc3RhY2tbY29kZXBvaW50XSA9IG5ld3N0YWNrW2NvZGVwb2ludF07XG4gICAgICAgIH1cblxuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRUb0RlYnVnQnVmZmVycyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveCA9IG5ldyBFbGVtZW50R3JvdXBzKHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXgpO1xuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5jb2xsaXNpb25Cb3gubWFrZVJvb21Gb3IoMCk7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIGFuZ2xlID0gLXRoaXMuY29sbGlzaW9uLmFuZ2xlO1xuICAgIHZhciB5U3RyZXRjaCA9IHRoaXMuY29sbGlzaW9uLnlTdHJldGNoO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZlYXR1cmUgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1tqXVtpID09PSAwID8gJ3RleHRDb2xsaXNpb25GZWF0dXJlJyA6ICdpY29uQ29sbGlzaW9uRmVhdHVyZSddO1xuICAgICAgICAgICAgaWYgKCFmZWF0dXJlKSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBib3hlcyA9IGZlYXR1cmUuYm94ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwOyBiIDwgYm94ZXMubGVuZ3RoOyBiKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYm94ID0gYm94ZXNbYl07XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IGJveC5hbmNob3I7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGwgPSBuZXcgUG9pbnQoYm94LngxLCBib3gueTEgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG4gICAgICAgICAgICAgICAgdmFyIHRyID0gbmV3IFBvaW50KGJveC54MiwgYm94LnkxICogeVN0cmV0Y2gpLl9yb3RhdGUoYW5nbGUpO1xuICAgICAgICAgICAgICAgIHZhciBibCA9IG5ldyBQb2ludChib3gueDEsIGJveC55MiAqIHlTdHJldGNoKS5fcm90YXRlKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICB2YXIgYnIgPSBuZXcgUG9pbnQoYm94LngyLCBib3gueTIgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4Wm9vbSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDI1LCB0aGlzLmNvbGxpc2lvbi56b29tICsgTWF0aC5sb2coYm94Lm1heFNjYWxlKSAvIE1hdGguTE4yKSk7XG4gICAgICAgICAgICAgICAgdmFyIHBsYWNlbWVudFpvb20gPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNSwgdGhpcy5jb2xsaXNpb24uem9vbSArIE1hdGgubG9nKGJveC5wbGFjZW1lbnRTY2FsZSkgLyBNYXRoLkxOMikpO1xuXG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIHRsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdHIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCB0ciwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJyLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgYnIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCBibCwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdGwsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveC5jdXJyZW50LnZlcnRleExlbmd0aCArPSA4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSB7XG5cbiAgICB0aGlzLnggPSBhbmNob3IueDtcbiAgICB0aGlzLnkgPSBhbmNob3IueTtcbiAgICB0aGlzLmhhc1RleHQgPSAhIXNoYXBlZFRleHQ7XG4gICAgdGhpcy5oYXNJY29uID0gISFzaGFwZWRJY29uO1xuXG4gICAgaWYgKHRoaXMuaGFzVGV4dCkge1xuICAgICAgICB0aGlzLmdseXBoUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRHbHlwaFF1YWRzKGFuY2hvciwgc2hhcGVkVGV4dCwgdGV4dEJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIHRleHRBbG9uZ0xpbmUpIDogW107XG4gICAgICAgIHRoaXMudGV4dENvbGxpc2lvbkZlYXR1cmUgPSBuZXcgQ29sbGlzaW9uRmVhdHVyZShsaW5lLCBhbmNob3IsIHNoYXBlZFRleHQsIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0ljb24pIHtcbiAgICAgICAgdGhpcy5pY29uUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRJY29uUXVhZHMoYW5jaG9yLCBzaGFwZWRJY29uLCBpY29uQm94U2NhbGUsIGxpbmUsIGxheW91dCwgaWNvbkFsb25nTGluZSkgOiBbXTtcbiAgICAgICAgdGhpcy5pY29uQ29sbGlzaW9uRmVhdHVyZSA9IG5ldyBDb2xsaXNpb25GZWF0dXJlKGxpbmUsIGFuY2hvciwgc2hhcGVkSWNvbiwgaWNvbkJveFNjYWxlLCBpY29uUGFkZGluZywgaWNvbkFsb25nTGluZSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvb3JkaW5hdGU7XG5cbi8qKlxuICogQSBjb29yZGluYXRlIGlzIGEgY29sdW1uLCByb3csIHpvb20gY29tYmluYXRpb24sIG9mdGVuIHVzZWRcbiAqIGFzIHRoZSBkYXRhIGNvbXBvbmVudCBvZiBhIHRpbGUuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IGNvbHVtblxuICogQHBhcmFtIHtOdW1iZXJ9IHJvd1xuICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIENvb3JkaW5hdGUoY29sdW1uLCByb3csIHpvb20pIHtcbiAgICB0aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICB0aGlzLnJvdyA9IHJvdztcbiAgICB0aGlzLnpvb20gPSB6b29tO1xufVxuXG5Db29yZGluYXRlLnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGNsb25lIG9mIHRoaXMgY29vcmRpbmF0ZSB0aGF0IGNhbiBiZSBtdXRhdGVkIHdpdGhvdXRcbiAgICAgKiBjaGFuZ2luZyB0aGUgb3JpZ2luYWwgY29vcmRpbmF0ZVxuICAgICAqXG4gICAgICogQHJldHVybnMge0Nvb3JkaW5hdGV9IGNsb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC5jbG9uZSgpO1xuICAgICAqIC8vIHNpbmNlIGNvb3JkIGlzIGNsb25lZCwgbW9kaWZ5aW5nIGEgcHJvcGVydHkgb2YgYzIgZG9lc1xuICAgICAqIC8vIG5vdCBtb2RpZnkgaXQuXG4gICAgICogYzIuem9vbSA9IDI7XG4gICAgICovXG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUodGhpcy5jb2x1bW4sIHRoaXMucm93LCB0aGlzLnpvb20pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIHRoaXMgY29vcmRpbmF0ZSB0byBhIGdpdmVuIHpvb20gbGV2ZWwuIFRoaXMgcmV0dXJucyBhIG5ld1xuICAgICAqIGNvb3JkaW5hdGUgb2JqZWN0LCBub3QgbXV0YXRpbmcgdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gem9vbVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSB6b29tZWQgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC56b29tVG8oMSk7XG4gICAgICogYzIgLy8gZXF1YWxzIG5ldyBDb29yZGluYXRlKDAsIDAsIDEpO1xuICAgICAqL1xuICAgIHpvb21UbzogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl96b29tVG8oem9vbSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTdWJ0cmFjdCB0aGUgY29sdW1uIGFuZCByb3cgdmFsdWVzIG9mIHRoaXMgY29vcmRpbmF0ZSBmcm9tIHRob3NlXG4gICAgICogb2YgYW5vdGhlciBjb29yZGluYXRlLiBUaGUgb3RoZXIgY29vcmRpbmF0IHdpbGwgYmUgem9vbWVkIHRvIHRoZVxuICAgICAqIHNhbWUgbGV2ZWwgYXMgYHRoaXNgIGJlZm9yZSB0aGUgc3VidHJhY3Rpb24gb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGMgb3RoZXIgY29vcmRpbmF0ZVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSByZXN1bHRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN1YjogZnVuY3Rpb24oYykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWIoYyk7IH0sXG5cbiAgICBfem9vbVRvOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHZhciBzY2FsZSA9IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAqPSBzY2FsZTtcbiAgICAgICAgdGhpcy5yb3cgKj0gc2NhbGU7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfc3ViOiBmdW5jdGlvbihjKSB7XG4gICAgICAgIGMgPSBjLnpvb21Ubyh0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAtPSBjLmNvbHVtbjtcbiAgICAgICAgdGhpcy5yb3cgLT0gYy5yb3c7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nO1xuXG52YXIgd3JhcCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpLndyYXA7XG5cbi8qKlxuICogQ3JlYXRlIGEgbGF0aXR1ZGUsIGxvbmdpdHVkZSBvYmplY3QgZnJvbSBhIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcGFpciBpbiBkZWdyZWVzLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiBhIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcG9pbnQsIGluIGRlZ3JlZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gbGF0IGxhdGl0dWRlXG4gKiBAcGFyYW0ge251bWJlcn0gbG5nIGxvbmdpdHVkZVxuICogQGV4YW1wbGVcbiAqIHZhciBsYXRsbmcgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDM3Ljc2LCAtMTIyLjQ0KTtcbiAqL1xuZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nKSB7XG4gICAgaWYgKGlzTmFOKGxhdCkgfHwgaXNOYU4obG5nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgTGF0TG5nIG9iamVjdDogKCcgKyBsYXQgKyAnLCAnICsgbG5nICsgJyknKTtcbiAgICB9XG4gICAgdGhpcy5sYXQgPSArbGF0O1xuICAgIHRoaXMubG5nID0gK2xuZztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBuZXcgYExhdExuZ2Agb2JqZWN0IHdob3NlIGxvbmdpdHVkZSBpcyB3cmFwcGVkIHRvIHRoZSByYW5nZSAoLTE4MCwgMTgwKS5cbiAqXG4gKiBAcmV0dXJucyB7TGF0TG5nfSB3cmFwcGVkIExhdExuZyBvYmplY3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9pbnQgPSBtYXBib3hnbC5MYXRMbmcoMCwgMjAwKTtcbiAqIHZhciB3cmFwcGVkID0gcG9pbnQud3JhcCgpO1xuICogd3JhcHBlZC5sbmc7IC8vID0gLTE2MFxuICovXG5MYXRMbmcucHJvdG90eXBlLndyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHdyYXAodGhpcy5sbmcsIC0xODAsIDE4MCkpO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IGFuIGFycmF5IHRvIGEgYExhdExuZ2Agb2JqZWN0LCBvciByZXR1cm4gYW4gZXhpc3RpbmcgYExhdExuZ2Agb2JqZWN0XG4gKiB1bmNoYW5nZWQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fExhdExuZ30gaW5wdXQgYGlucHV0YCB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7TGF0TG5nfSBMYXRMbmcgb2JqZWN0IG9yIG9yaWdpbmFsIGlucHV0XG4gKiBAZXhhbXBsZVxuICogdmFyIGxsID0gbWFwYm94Z2wuTGF0TG5nLmNvbnZlcnQoWzEwLCAxMF0pO1xuICogdmFyIGxsMiA9IG5ldyBtYXBib3hnbC5MYXRMbmcoMTAsIDEwKTtcbiAqIGxsIC8vID0gbGwyXG4gKi9cbkxhdExuZy5jb252ZXJ0ID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKGlucHV0WzBdLCBpbnB1dFsxXSk7XG4gICAgfVxuICAgIHJldHVybiBpbnB1dDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nQm91bmRzO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJvdW5kaW5nIGJveCBmcm9tIHRoZSBnaXZlbiBwYWlyIG9mIHBvaW50cy4gSWYgcGFyYW1ldGVyZXMgYXJlIG9taXR0ZWQsIGEgYG51bGxgIGJvdW5kaW5nIGJveCBpcyBjcmVhdGVkLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdCb3VuZHNcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiByZWN0YW5ndWxhciBib3ggb24gdGhlIGVhcnRoLCBkZWZpbmVkIGJ5IGl0cyBzb3V0aHdlc3QgYW5kIG5vcnRoZWFzdCBwb2ludHMgaW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS5cbiAqIEBwYXJhbSB7TGF0TG5nfSBzdyBzb3V0aHdlc3RcbiAqIEBwYXJhbSB7TGF0TG5nfSBuZSBub3J0aGVhc3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgc3cgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDAsIDApO1xuICogdmFyIG5lID0gbmV3IG1hcGJveGdsLkxhdExuZygxMCwgLTEwKTtcbiAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKHN3LCBuZSk7XG4gKlxuICovXG5mdW5jdGlvbiBMYXRMbmdCb3VuZHMoc3csIG5lKSB7XG4gICAgaWYgKCFzdykgcmV0dXJuO1xuXG4gICAgdmFyIGxhdGxuZ3MgPSBuZSA/IFtzdywgbmVdIDogc3c7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB0aGlzLmV4dGVuZChsYXRsbmdzW2ldKTtcbiAgICB9XG59XG5cbkxhdExuZ0JvdW5kcy5wcm90b3R5cGUgPSB7XG5cbiAgICAvKipcbiAgICAgKiBFeHRlbmQgdGhlIGJvdW5kcyB0byBpbmNsdWRlIGEgZ2l2ZW4gTGF0TG5nIG9yIExhdExuZ0JvdW5kcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TGF0TG5nfExhdExuZ0JvdW5kc30gb2JqIG9iamVjdCB0byBleHRlbmQgdG9cbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nQm91bmRzfSBgdGhpc2BcbiAgICAgKi9cbiAgICBleHRlbmQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICB2YXIgc3cgPSB0aGlzLl9zdyxcbiAgICAgICAgICAgIG5lID0gdGhpcy5fbmUsXG4gICAgICAgICAgICBzdzIsIG5lMjtcblxuICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgICAgICBzdzIgPSBvYmo7XG4gICAgICAgICAgICBuZTIgPSBvYmo7XG5cbiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcbiAgICAgICAgICAgIHN3MiA9IG9iai5fc3c7XG4gICAgICAgICAgICBuZTIgPSBvYmouX25lO1xuXG4gICAgICAgICAgICBpZiAoIXN3MiB8fCAhbmUyKSByZXR1cm4gdGhpcztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKExhdExuZy5jb252ZXJ0KG9iaikgfHwgTGF0TG5nQm91bmRzLmNvbnZlcnQob2JqKSkgOiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzdyAmJiAhbmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N3ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcbiAgICAgICAgICAgIHRoaXMuX25lID0gbmV3IExhdExuZyhuZTIubGF0LCBuZTIubG5nKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcbiAgICAgICAgICAgIHN3LmxuZyA9IE1hdGgubWluKHN3Mi5sbmcsIHN3LmxuZyk7XG4gICAgICAgICAgICBuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xuICAgICAgICAgICAgbmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHBvaW50IGVxdWlkaXN0YW50IGZyb20gdGhpcyBib3gncyBjb3JuZXJzXG4gICAgICogQHJldHVybnMge0xhdExuZ30gY2VudGVycG9pbnRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygxMCwgMTApLFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygtMTAsIC0xMCk7XG4gICAgICogYm91bmRzLmdldENlbnRlcigpOyAvLyBlcXVhbHMgbWFwYm94Z2wuTGF0TG5nKDAsIDApXG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmcoKHRoaXMuX3N3LmxhdCArIHRoaXMuX25lLmxhdCkgLyAyLCAodGhpcy5fc3cubG5nICsgdGhpcy5fbmUubG5nKSAvIDIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGh3ZXN0IGNvcm5lclxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9IHNvdXRod2VzdFxuICAgICAqL1xuICAgIGdldFNvdXRoV2VzdDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdzsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBub3J0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbm9ydGhlYXN0XG4gICAgICovXG4gICAgZ2V0Tm9ydGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRod2VzdCBjb3JuZXJcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBub3J0aHdlc3RcbiAgICAgKi9cbiAgICBnZXROb3J0aFdlc3Q6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldE5vcnRoKCksIHRoaXMuZ2V0V2VzdCgpKTsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBzb3V0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gc291dGhlYXN0XG4gICAgICovXG4gICAgZ2V0U291dGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgd2VzdCBlZGdlIGxvbmdpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHdlc3RcbiAgICAgKi9cbiAgICBnZXRXZXN0OiAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdy5sbmc7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGggZWRnZSBsYXRpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHNvdXRoXG4gICAgICovXG4gICAgZ2V0U291dGg6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fc3cubGF0OyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IGVhc3QgZWRnZSBsb25naXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBlYXN0XG4gICAgICovXG4gICAgZ2V0RWFzdDogIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fbmUubG5nOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRoIGVkZ2UgbGF0aXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBub3J0aFxuICAgICAqL1xuICAgIGdldE5vcnRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lLmxhdDsgfVxufTtcblxuLyoqXG4gKiBjb25zdHJ1Y3RzIExhdExuZ0JvdW5kcyBmcm9tIGFuIGFycmF5IGlmIG5lY2Vzc2FyeVxuICogQHBhcmFtIHtMYXRMbmdCb3VuZHN8Kn0gYSBhbnkgaW5wdXRcbiAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN8ZmFsc2V9XG4gKiBAZXhhbXBsZVxuICogLy8gY2FsbHMgTGF0TG5nLmNvbnZlcnQgaW50ZXJuYWxseSB0b1xuICogLy8gc3VwcG9ydCBhcnJheXMgYXMgbGF0bG5nIHZhbHVlc1xuICogTGF0TG5nQm91bmRzLmNvbnZlcnQoW1stMTAsIC0xMF0sIFsxMCwgMTBdXSk7XG4gKi9cbkxhdExuZ0JvdW5kcy5jb252ZXJ0ID0gZnVuY3Rpb24gKGEpIHtcbiAgICBpZiAoIWEgfHwgYSBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykgcmV0dXJuIGE7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpLFxuICAgIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuL2Nvb3JkaW5hdGUnKSxcbiAgICB3cmFwID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJykud3JhcCxcbiAgICBpbnRlcnAgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyksXG4gICAgdmVjNCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLnZlYzQsXG4gICAgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhbnNmb3JtO1xuXG4vKlxuICogQSBzaW5nbGUgdHJhbnNmb3JtLCBnZW5lcmFsbHkgdXNlZCBmb3IgYSBzaW5nbGUgdGlsZSB0byBiZVxuICogc2NhbGVkLCByb3RhdGVkLCBhbmQgem9vbWVkLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtaW5ab29tXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4Wm9vbVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gVHJhbnNmb3JtKG1pblpvb20sIG1heFpvb20pIHtcbiAgICB0aGlzLnRpbGVTaXplID0gNTEyOyAvLyBjb25zdGFudFxuXG4gICAgdGhpcy5fbWluWm9vbSA9IG1pblpvb20gfHwgMDtcbiAgICB0aGlzLl9tYXhab29tID0gbWF4Wm9vbSB8fCAyMjtcblxuICAgIHRoaXMubGF0UmFuZ2UgPSBbLTg1LjA1MTEzLCA4NS4wNTExM107XG5cbiAgICB0aGlzLndpZHRoID0gMDtcbiAgICB0aGlzLmhlaWdodCA9IDA7XG4gICAgdGhpcy56b29tID0gMDtcbiAgICB0aGlzLmNlbnRlciA9IG5ldyBMYXRMbmcoMCwgMCk7XG4gICAgdGhpcy5hbmdsZSA9IDA7XG4gICAgdGhpcy5fYWx0aXR1ZGUgPSAxLjU7XG4gICAgdGhpcy5fcGl0Y2ggPSAwO1xufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlID0ge1xuICAgIGdldCBtaW5ab29tKCkgeyByZXR1cm4gdGhpcy5fbWluWm9vbTsgfSxcbiAgICBzZXQgbWluWm9vbSh6b29tKSB7XG4gICAgICAgIHRoaXMuX21pblpvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnpvb20gPSBNYXRoLm1heCh0aGlzLnpvb20sIHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXQgbWF4Wm9vbSgpIHsgcmV0dXJuIHRoaXMuX21heFpvb207IH0sXG4gICAgc2V0IG1heFpvb20oem9vbSkge1xuICAgICAgICB0aGlzLl9tYXhab29tID0gem9vbTtcbiAgICAgICAgdGhpcy56b29tID0gTWF0aC5taW4odGhpcy56b29tLCB6b29tKTtcbiAgICB9LFxuXG4gICAgZ2V0IHdvcmxkU2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUgKiB0aGlzLnNjYWxlO1xuICAgIH0sXG5cbiAgICBnZXQgY2VudGVyUG9pbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemUuX2RpdigyKTtcbiAgICB9LFxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuICAgIH0sXG5cbiAgICBnZXQgYmVhcmluZygpIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLmFuZ2xlIC8gTWF0aC5QSSAqIDE4MDtcbiAgICB9LFxuICAgIHNldCBiZWFyaW5nKGJlYXJpbmcpIHtcbiAgICAgICAgdGhpcy5hbmdsZSA9IC13cmFwKGJlYXJpbmcsIC0xODAsIDE4MCkgKiBNYXRoLlBJIC8gMTgwO1xuICAgIH0sXG5cbiAgICBnZXQgcGl0Y2goKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9waXRjaCAvIE1hdGguUEkgKiAxODA7XG4gICAgfSxcbiAgICBzZXQgcGl0Y2gocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5fcGl0Y2ggPSBNYXRoLm1pbig2MCwgcGl0Y2gpIC8gMTgwICogTWF0aC5QSTtcbiAgICB9LFxuXG4gICAgZ2V0IGFsdGl0dWRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWx0aXR1ZGU7XG4gICAgfSxcbiAgICBzZXQgYWx0aXR1ZGUoYWx0aXR1ZGUpIHtcbiAgICAgICAgdGhpcy5fYWx0aXR1ZGUgPSBNYXRoLm1heCgwLjc1LCBhbHRpdHVkZSk7XG4gICAgfSxcblxuICAgIGdldCB6b29tKCkgeyByZXR1cm4gdGhpcy5fem9vbTsgfSxcbiAgICBzZXQgem9vbSh6b29tKSB7XG4gICAgICAgIHpvb20gPSBNYXRoLm1pbihNYXRoLm1heCh6b29tLCB0aGlzLm1pblpvb20pLCB0aGlzLm1heFpvb20pO1xuICAgICAgICB0aGlzLl96b29tID0gem9vbTtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHRoaXMuem9vbVNjYWxlKHpvb20pO1xuICAgICAgICB0aGlzLnRpbGVab29tID0gTWF0aC5mbG9vcih6b29tKTtcbiAgICAgICAgdGhpcy56b29tRnJhY3Rpb24gPSB6b29tIC0gdGhpcy50aWxlWm9vbTtcbiAgICAgICAgdGhpcy5fY29uc3RyYWluKCk7XG4gICAgfSxcblxuICAgIHpvb21TY2FsZTogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gTWF0aC5wb3coMiwgem9vbSk7IH0sXG4gICAgc2NhbGVab29tOiBmdW5jdGlvbihzY2FsZSkgeyByZXR1cm4gTWF0aC5sb2coc2NhbGUpIC8gTWF0aC5MTjI7IH0sXG5cbiAgICBwcm9qZWN0OiBmdW5jdGlvbihsYXRsbmcsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IFBvaW50KFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcsIHdvcmxkU2l6ZSksXG4gICAgICAgICAgICB0aGlzLmxhdFkobGF0bG5nLmxhdCwgd29ybGRTaXplKSk7XG4gICAgfSxcblxuICAgIHVucHJvamVjdDogZnVuY3Rpb24ocG9pbnQsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZyhcbiAgICAgICAgICAgIHRoaXMueUxhdChwb2ludC55LCB3b3JsZFNpemUpLFxuICAgICAgICAgICAgdGhpcy54TG5nKHBvaW50LngsIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBnZXQgeCgpIHsgcmV0dXJuIHRoaXMubG5nWCh0aGlzLmNlbnRlci5sbmcpOyB9LFxuICAgIGdldCB5KCkgeyByZXR1cm4gdGhpcy5sYXRZKHRoaXMuY2VudGVyLmxhdCk7IH0sXG5cbiAgICBnZXQgcG9pbnQoKSB7IHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpOyB9LFxuXG4gICAgLyoqXG4gICAgICogbGF0L2xvbiA8LT4gYWJzb2x1dGUgcGl4ZWwgY29vcmRzIGNvbnZlcnNpb25cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbG9uXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG5nWDogZnVuY3Rpb24obG9uLCB3b3JsZFNpemUpIHtcbiAgICAgICAgcmV0dXJuICgxODAgKyBsb24pICogKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLyAzNjA7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBsYXRpdHVkZSB0byBhYnNvbHV0ZSB5IGNvb3JkXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGF0XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbGF0WTogZnVuY3Rpb24obGF0LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkgPSAxODAgLyBNYXRoLlBJICogTWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSSAvIDQgKyBsYXQgKiBNYXRoLlBJIC8gMzYwKSk7XG4gICAgICAgIHJldHVybiAoMTgwIC0geSkgKiAod29ybGRTaXplIHx8IHRoaXMud29ybGRTaXplKSAvIDM2MDtcbiAgICB9LFxuXG4gICAgeExuZzogZnVuY3Rpb24oeCwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiB4ICogMzYwIC8gKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLSAxODA7XG4gICAgfSxcbiAgICB5TGF0OiBmdW5jdGlvbih5LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkyID0gMTgwIC0geSAqIDM2MCAvICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpO1xuICAgICAgICByZXR1cm4gMzYwIC8gTWF0aC5QSSAqIE1hdGguYXRhbihNYXRoLmV4cCh5MiAqIE1hdGguUEkgLyAxODApKSAtIDkwO1xuICAgIH0sXG5cbiAgICBwYW5CeTogZnVuY3Rpb24ob2Zmc2V0KSB7XG4gICAgICAgIHZhciBwb2ludCA9IHRoaXMuY2VudGVyUG9pbnQuX2FkZChvZmZzZXQpO1xuICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMucG9pbnRMb2NhdGlvbihwb2ludCk7XG4gICAgICAgIHRoaXMuX2NvbnN0cmFpbigpO1xuICAgIH0sXG5cbiAgICBzZXRMb2NhdGlvbkF0UG9pbnQ6IGZ1bmN0aW9uKGxhdGxuZywgcG9pbnQpIHtcbiAgICAgICAgdmFyIGMgPSB0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpO1xuICAgICAgICB2YXIgY29vcmRBdFBvaW50ID0gdGhpcy5wb2ludENvb3JkaW5hdGUocG9pbnQpO1xuICAgICAgICB2YXIgY29vcmRDZW50ZXIgPSB0aGlzLnBvaW50Q29vcmRpbmF0ZSh0aGlzLmNlbnRlclBvaW50KTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlID0gY29vcmRBdFBvaW50Ll9zdWIoYyk7XG4gICAgICAgIHRoaXMuY2VudGVyID0gdGhpcy5jb29yZGluYXRlTG9jYXRpb24oY29vcmRDZW50ZXIuX3N1Yih0cmFuc2xhdGUpKTtcblxuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgc2V0Wm9vbUFyb3VuZDogZnVuY3Rpb24oem9vbSwgY2VudGVyKSB7XG4gICAgICAgIHZhciBwID0gdGhpcy5sb2NhdGlvblBvaW50KGNlbnRlcik7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHRoaXMuc2V0TG9jYXRpb25BdFBvaW50KGNlbnRlciwgcCk7XG4gICAgfSxcblxuICAgIHNldEJlYXJpbmdBcm91bmQ6IGZ1bmN0aW9uKGJlYXJpbmcsIGNlbnRlcikge1xuICAgICAgICB2YXIgcCA9IHRoaXMubG9jYXRpb25Qb2ludChjZW50ZXIpO1xuICAgICAgICB0aGlzLmJlYXJpbmcgPSBiZWFyaW5nO1xuICAgICAgICB0aGlzLnNldExvY2F0aW9uQXRQb2ludChjZW50ZXIsIHApO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGxvY2F0aW9uLCByZXR1cm4gdGhlIHNjcmVlbiBwb2ludCB0aGF0IGNvcnJlc3BvbmRzIHRvIGl0XG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZyBsb2NhdGlvblxuICAgICAqIEByZXR1cm5zIHtQb2ludH0gc2NyZWVuIHBvaW50XG4gICAgICovXG4gICAgbG9jYXRpb25Qb2ludDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBwb2ludCBvbiBzY3JlZW4sIHJldHVybiBpdHMgbGF0bG5nXG4gICAgICogQHBhcmFtIHtQb2ludH0gcCBzY3JlZW4gcG9pbnRcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBsYXRsbmcgbG9jYXRpb25cbiAgICAgKi9cbiAgICBwb2ludExvY2F0aW9uOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZShwKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGxhdGxuZywgcmV0dXJuIGFuIHVucm91bmRlZFxuICAgICAqIGNvb3JkaW5hdGUgdGhhdCByZXByZXNlbnRzIGl0IGF0IHRoaXMgdHJhbnNmb3JtJ3Mgem9vbSBsZXZlbCBhbmRcbiAgICAgKiB3b3JsZHNpemUuXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfVxuICAgICAqL1xuICAgIGxvY2F0aW9uQ29vcmRpbmF0ZTogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHZhciBrID0gdGhpcy56b29tU2NhbGUodGhpcy50aWxlWm9vbSkgLyB0aGlzLndvcmxkU2l6ZTtcbiAgICAgICAgcmV0dXJuIG5ldyBDb29yZGluYXRlKFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcpICogayxcbiAgICAgICAgICAgIHRoaXMubGF0WShsYXRsbmcubGF0KSAqIGssXG4gICAgICAgICAgICB0aGlzLnRpbGVab29tKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBDb29yZGluYXRlLCByZXR1cm4gaXRzIGdlb2dyYXBoaWNhbCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbGF0bG5nXG4gICAgICovXG4gICAgY29vcmRpbmF0ZUxvY2F0aW9uOiBmdW5jdGlvbihjb29yZCkge1xuICAgICAgICB2YXIgd29ybGRTaXplID0gdGhpcy56b29tU2NhbGUoY29vcmQuem9vbSk7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKFxuICAgICAgICAgICAgdGhpcy55TGF0KGNvb3JkLnJvdywgd29ybGRTaXplKSxcbiAgICAgICAgICAgIHRoaXMueExuZyhjb29yZC5jb2x1bW4sIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBwb2ludENvb3JkaW5hdGU6IGZ1bmN0aW9uKHAsIHRhcmdldFopIHtcblxuICAgICAgICBpZiAodGFyZ2V0WiA9PT0gdW5kZWZpbmVkKSB0YXJnZXRaID0gMDtcblxuICAgICAgICB2YXIgbWF0cml4ID0gdGhpcy5jb29yZGluYXRlUG9pbnRNYXRyaXgodGhpcy50aWxlWm9vbSk7XG4gICAgICAgIHZhciBpbnZlcnRlZCA9IG1hdDQuaW52ZXJ0KG5ldyBGbG9hdDY0QXJyYXkoMTYpLCBtYXRyaXgpO1xuXG4gICAgICAgIGlmICghaW52ZXJ0ZWQpIHRocm93IFwiZmFpbGVkIHRvIGludmVydCBtYXRyaXhcIjtcblxuICAgICAgICAvLyBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSBjb3JyZWN0IHByb2plY3RlZCB6IHZhbHVlIGZvciB0aGUgcG9pbnQsXG4gICAgICAgIC8vIHVucHJvamVjdCB0d28gcG9pbnRzIHRvIGdldCBhIGxpbmUgYW5kIHRoZW4gZmluZCB0aGUgcG9pbnQgb24gdGhhdFxuICAgICAgICAvLyBsaW5lIHdpdGggej0wXG5cbiAgICAgICAgdmFyIGNvb3JkMCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW3AueCwgcC55LCAwLCAxXSwgaW52ZXJ0ZWQpO1xuICAgICAgICB2YXIgY29vcmQxID0gdmVjNC50cmFuc2Zvcm1NYXQ0KFtdLCBbcC54LCBwLnksIDEsIDFdLCBpbnZlcnRlZCk7XG5cbiAgICAgICAgdmFyIHcwID0gY29vcmQwWzNdO1xuICAgICAgICB2YXIgdzEgPSBjb29yZDFbM107XG4gICAgICAgIHZhciB4MCA9IGNvb3JkMFswXSAvIHcwO1xuICAgICAgICB2YXIgeDEgPSBjb29yZDFbMF0gLyB3MTtcbiAgICAgICAgdmFyIHkwID0gY29vcmQwWzFdIC8gdzA7XG4gICAgICAgIHZhciB5MSA9IGNvb3JkMVsxXSAvIHcxO1xuICAgICAgICB2YXIgejAgPSBjb29yZDBbMl0gLyB3MDtcbiAgICAgICAgdmFyIHoxID0gY29vcmQxWzJdIC8gdzE7XG5cblxuICAgICAgICB2YXIgdCA9IHowID09PSB6MSA/IDAgOiAodGFyZ2V0WiAtIHowKSAvICh6MSAtIHowKTtcblxuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUoXG4gICAgICAgICAgICBpbnRlcnAoeDAsIHgxLCB0KSxcbiAgICAgICAgICAgIGludGVycCh5MCwgeTEsIHQpLFxuICAgICAgICAgICAgdGhpcy50aWxlWm9vbSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgY29vcmRpbmF0ZSwgcmV0dXJuIHRoZSBzY3JlZW4gcG9pbnQgdGhhdCBjb3JyZXNwb25kcyB0byBpdFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7UG9pbnR9IHNjcmVlbiBwb2ludFxuICAgICAqL1xuICAgIGNvb3JkaW5hdGVQb2ludDogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMuY29vcmRpbmF0ZVBvaW50TWF0cml4KGNvb3JkLnpvb20pO1xuICAgICAgICB2YXIgcCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW2Nvb3JkLmNvbHVtbiwgY29vcmQucm93LCAwLCAxXSwgbWF0cml4KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChwWzBdIC8gcFszXSwgcFsxXSAvIHBbM10pO1xuICAgIH0sXG5cbiAgICBjb29yZGluYXRlUG9pbnRNYXRyaXg6IGZ1bmN0aW9uKHopIHtcbiAgICAgICAgdmFyIHByb2ogPSB0aGlzLmdldFByb2pNYXRyaXgoKTtcbiAgICAgICAgdmFyIHNjYWxlID0gdGhpcy53b3JsZFNpemUgLyB0aGlzLnpvb21TY2FsZSh6KTtcbiAgICAgICAgbWF0NC5zY2FsZShwcm9qLCBwcm9qLCBbc2NhbGUsIHNjYWxlLCAxXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkocHJvaiwgdGhpcy5nZXRQaXhlbE1hdHJpeCgpLCBwcm9qKTtcbiAgICAgICAgcmV0dXJuIHByb2o7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIGNvbnZlcnRzIGdsIGNvb3JkaW5hdGVzIC0xLi4xIHRvIHBpeGVscyAwLi53aWR0aFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IG1hdHJpeFxuICAgICAqL1xuICAgIGdldFBpeGVsTWF0cml4OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG0gPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFt0aGlzLndpZHRoIC8gMiwgLXRoaXMuaGVpZ2h0IC8gMiwgMV0pO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbMSwgLTEsIDBdKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgfSxcblxuICAgIF9jb25zdHJhaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VudGVyKSByZXR1cm47XG5cbiAgICAgICAgdmFyIG1pblksIG1heFksIG1pblgsIG1heFgsIHN5LCBzeCwgeDIsIHkyLFxuICAgICAgICAgICAgc2l6ZSA9IHRoaXMuc2l6ZTtcblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgbWluWSA9IHRoaXMubGF0WSh0aGlzLmxhdFJhbmdlWzFdKTtcbiAgICAgICAgICAgIG1heFkgPSB0aGlzLmxhdFkodGhpcy5sYXRSYW5nZVswXSk7XG4gICAgICAgICAgICBzeSA9IG1heFkgLSBtaW5ZIDwgc2l6ZS55ID8gc2l6ZS55IC8gKG1heFkgLSBtaW5ZKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgbWluWCA9IHRoaXMubG5nWCh0aGlzLmxuZ1JhbmdlWzBdKTtcbiAgICAgICAgICAgIG1heFggPSB0aGlzLmxuZ1godGhpcy5sbmdSYW5nZVsxXSk7XG4gICAgICAgICAgICBzeCA9IG1heFggLSBtaW5YIDwgc2l6ZS54ID8gc2l6ZS54IC8gKG1heFggLSBtaW5YKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob3cgbXVjaCB0aGUgbWFwIHNob3VsZCBzY2FsZSB0byBmaXQgdGhlIHNjcmVlbiBpbnRvIGdpdmVuIGxhdGl0dWRlL2xvbmdpdHVkZSByYW5nZXNcbiAgICAgICAgdmFyIHMgPSBNYXRoLm1heChzeCB8fCAwLCBzeSB8fCAwKTtcblxuICAgICAgICBpZiAocykge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnVucHJvamVjdChuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgc3ggPyAobWF4WCArIG1pblgpIC8gMiA6IHRoaXMueCxcbiAgICAgICAgICAgICAgICBzeSA/IChtYXhZICsgbWluWSkgLyAyIDogdGhpcy55KSk7XG4gICAgICAgICAgICB0aGlzLnpvb20gKz0gdGhpcy5zY2FsZVpvb20ocyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHkgPSB0aGlzLnksXG4gICAgICAgICAgICAgICAgaDIgPSBzaXplLnkgLyAyO1xuXG4gICAgICAgICAgICBpZiAoeSAtIGgyIDwgbWluWSkgeTIgPSBtaW5ZICsgaDI7XG4gICAgICAgICAgICBpZiAoeSArIGgyID4gbWF4WSkgeTIgPSBtYXhZIC0gaDI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHggPSB0aGlzLngsXG4gICAgICAgICAgICAgICAgdzIgPSBzaXplLnggLyAyO1xuXG4gICAgICAgICAgICBpZiAoeCAtIHcyIDwgbWluWCkgeDIgPSBtaW5YICsgdzI7XG4gICAgICAgICAgICBpZiAoeCArIHcyID4gbWF4WCkgeDIgPSBtYXhYIC0gdzI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwYW4gdGhlIG1hcCBpZiB0aGUgc2NyZWVuIGdvZXMgb2ZmIHRoZSByYW5nZVxuICAgICAgICBpZiAoeDIgIT09IHVuZGVmaW5lZCB8fCB5MiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMudW5wcm9qZWN0KG5ldyBQb2ludChcbiAgICAgICAgICAgICAgICB4MiAhPT0gdW5kZWZpbmVkID8geDIgOiB0aGlzLngsXG4gICAgICAgICAgICAgICAgeTIgIT09IHVuZGVmaW5lZCA/IHkyIDogdGhpcy55KSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZ2V0UHJvak1hdHJpeDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtID0gbmV3IEZsb2F0NjRBcnJheSgxNik7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgY2VudGVyIHBvaW50IHRvIHRoZSBjZW50ZXIgdG9wIGluIGFsdGl0dWRlIHVuaXRzIHVzaW5nIGxhdyBvZiBzaW5lcy5cbiAgICAgICAgdmFyIGhhbGZGb3YgPSBNYXRoLmF0YW4oMC41IC8gdGhpcy5hbHRpdHVkZSk7XG4gICAgICAgIHZhciB0b3BIYWxmU3VyZmFjZURpc3RhbmNlID0gTWF0aC5zaW4oaGFsZkZvdikgKiB0aGlzLmFsdGl0dWRlIC8gTWF0aC5zaW4oTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCAtIGhhbGZGb3YpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgeiB2YWx1ZSBvZiB0aGUgZmFydGhlc3QgZnJhZ21lbnQgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAgICAgIHZhciBmYXJaID0gTWF0aC5jb3MoTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCkgKiB0b3BIYWxmU3VyZmFjZURpc3RhbmNlICsgdGhpcy5hbHRpdHVkZTtcblxuICAgICAgICBtYXQ0LnBlcnNwZWN0aXZlKG0sIDIgKiBNYXRoLmF0YW4oKHRoaXMuaGVpZ2h0IC8gMikgLyB0aGlzLmFsdGl0dWRlKSwgdGhpcy53aWR0aCAvIHRoaXMuaGVpZ2h0LCAwLjEsIGZhclopO1xuXG4gICAgICAgIG1hdDQudHJhbnNsYXRlKG0sIG0sIFswLCAwLCAtdGhpcy5hbHRpdHVkZV0pO1xuXG4gICAgICAgIC8vIEFmdGVyIHRoZSByb3RhdGVYLCB6IHZhbHVlcyBhcmUgaW4gcGl4ZWwgdW5pdHMuIENvbnZlcnQgdGhlbSB0b1xuICAgICAgICAvLyBhbHRpdHVkZSB1bml0ZXMuIDEgYWx0aXR1ZGUgdW5pdCA9IHRoZSBzY3JlZW4gaGVpZ2h0LlxuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFsxLCAtMSwgMSAvIHRoaXMuaGVpZ2h0XSk7XG5cbiAgICAgICAgbWF0NC5yb3RhdGVYKG0sIG0sIHRoaXMuX3BpdGNoKTtcbiAgICAgICAgbWF0NC5yb3RhdGVaKG0sIG0sIHRoaXMuYW5nbGUpO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbLXRoaXMueCwgLXRoaXMueSwgMF0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBGb250IGRhdGEgRnJvbSBIZXJzaGV5IFNpbXBsZXggRm9udFxuLy8gaHR0cDovL3BhdWxib3Vya2UubmV0L2RhdGFmb3JtYXRzL2hlcnNoZXkvXG52YXIgc2ltcGxleEZvbnQgPSB7XG4gICAgXCIgXCI6IFsxNiwgW11dLFxuICAgIFwiIVwiOiBbMTAsIFs1LCAyMSwgNSwgNywgLTEsIC0xLCA1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCJcXFwiXCI6IFsxNiwgWzQsIDIxLCA0LCAxNCwgLTEsIC0xLCAxMiwgMjEsIDEyLCAxNF1dLFxuICAgIFwiI1wiOiBbMjEsIFsxMSwgMjUsIDQsIC03LCAtMSwgLTEsIDE3LCAyNSwgMTAsIC03LCAtMSwgLTEsIDQsIDEyLCAxOCwgMTIsIC0xLCAtMSwgMywgNiwgMTcsIDZdXSxcbiAgICBcIiRcIjogWzIwLCBbOCwgMjUsIDgsIC00LCAtMSwgLTEsIDEyLCAyNSwgMTIsIC00LCAtMSwgLTEsIDE3LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxLCA1LCAyMCwgMywgMTgsIDMsIDE2LCA0LCAxNCwgNSwgMTMsIDcsIDEyLCAxMywgMTAsIDE1LCA5LCAxNiwgOCwgMTcsIDYsIDE3LCAzLCAxNSwgMSwgMTIsIDAsIDgsIDAsIDUsIDEsIDMsIDNdXSxcbiAgICBcIiVcIjogWzI0LCBbMjEsIDIxLCAzLCAwLCAtMSwgLTEsIDgsIDIxLCAxMCwgMTksIDEwLCAxNywgOSwgMTUsIDcsIDE0LCA1LCAxNCwgMywgMTYsIDMsIDE4LCA0LCAyMCwgNiwgMjEsIDgsIDIxLCAxMCwgMjAsIDEzLCAxOSwgMTYsIDE5LCAxOSwgMjAsIDIxLCAyMSwgLTEsIC0xLCAxNywgNywgMTUsIDYsIDE0LCA0LCAxNCwgMiwgMTYsIDAsIDE4LCAwLCAyMCwgMSwgMjEsIDMsIDIxLCA1LCAxOSwgNywgMTcsIDddXSxcbiAgICBcIiZcIjogWzI2LCBbMjMsIDEyLCAyMywgMTMsIDIyLCAxNCwgMjEsIDE0LCAyMCwgMTMsIDE5LCAxMSwgMTcsIDYsIDE1LCAzLCAxMywgMSwgMTEsIDAsIDcsIDAsIDUsIDEsIDQsIDIsIDMsIDQsIDMsIDYsIDQsIDgsIDUsIDksIDEyLCAxMywgMTMsIDE0LCAxNCwgMTYsIDE0LCAxOCwgMTMsIDIwLCAxMSwgMjEsIDksIDIwLCA4LCAxOCwgOCwgMTYsIDksIDEzLCAxMSwgMTAsIDE2LCAzLCAxOCwgMSwgMjAsIDAsIDIyLCAwLCAyMywgMSwgMjMsIDJdXSxcbiAgICBcIidcIjogWzEwLCBbNSwgMTksIDQsIDIwLCA1LCAyMSwgNiwgMjAsIDYsIDE4LCA1LCAxNiwgNCwgMTVdXSxcbiAgICBcIihcIjogWzE0LCBbMTEsIDI1LCA5LCAyMywgNywgMjAsIDUsIDE2LCA0LCAxMSwgNCwgNywgNSwgMiwgNywgLTIsIDksIC01LCAxMSwgLTddXSxcbiAgICBcIilcIjogWzE0LCBbMywgMjUsIDUsIDIzLCA3LCAyMCwgOSwgMTYsIDEwLCAxMSwgMTAsIDcsIDksIDIsIDcsIC0yLCA1LCAtNSwgMywgLTddXSxcbiAgICBcIipcIjogWzE2LCBbOCwgMjEsIDgsIDksIC0xLCAtMSwgMywgMTgsIDEzLCAxMiwgLTEsIC0xLCAxMywgMTgsIDMsIDEyXV0sXG4gICAgXCIrXCI6IFsyNiwgWzEzLCAxOCwgMTMsIDAsIC0xLCAtMSwgNCwgOSwgMjIsIDldXSxcbiAgICBcIixcIjogWzEwLCBbNiwgMSwgNSwgMCwgNCwgMSwgNSwgMiwgNiwgMSwgNiwgLTEsIDUsIC0zLCA0LCAtNF1dLFxuICAgIFwiLVwiOiBbMjYsIFs0LCA5LCAyMiwgOV1dLFxuICAgIFwiLlwiOiBbMTAsIFs1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCIvXCI6IFsyMiwgWzIwLCAyNSwgMiwgLTddXSxcbiAgICBcIjBcIjogWzIwLCBbOSwgMjEsIDYsIDIwLCA0LCAxNywgMywgMTIsIDMsIDksIDQsIDQsIDYsIDEsIDksIDAsIDExLCAwLCAxNCwgMSwgMTYsIDQsIDE3LCA5LCAxNywgMTIsIDE2LCAxNywgMTQsIDIwLCAxMSwgMjEsIDksIDIxXV0sXG4gICAgXCIxXCI6IFsyMCwgWzYsIDE3LCA4LCAxOCwgMTEsIDIxLCAxMSwgMF1dLFxuICAgIFwiMlwiOiBbMjAsIFs0LCAxNiwgNCwgMTcsIDUsIDE5LCA2LCAyMCwgOCwgMjEsIDEyLCAyMSwgMTQsIDIwLCAxNSwgMTksIDE2LCAxNywgMTYsIDE1LCAxNSwgMTMsIDEzLCAxMCwgMywgMCwgMTcsIDBdXSxcbiAgICBcIjNcIjogWzIwLCBbNSwgMjEsIDE2LCAyMSwgMTAsIDEzLCAxMywgMTMsIDE1LCAxMiwgMTYsIDExLCAxNywgOCwgMTcsIDYsIDE2LCAzLCAxNCwgMSwgMTEsIDAsIDgsIDAsIDUsIDEsIDQsIDIsIDMsIDRdXSxcbiAgICBcIjRcIjogWzIwLCBbMTMsIDIxLCAzLCA3LCAxOCwgNywgLTEsIC0xLCAxMywgMjEsIDEzLCAwXV0sXG4gICAgXCI1XCI6IFsyMCwgWzE1LCAyMSwgNSwgMjEsIDQsIDEyLCA1LCAxMywgOCwgMTQsIDExLCAxNCwgMTQsIDEzLCAxNiwgMTEsIDE3LCA4LCAxNywgNiwgMTYsIDMsIDE0LCAxLCAxMSwgMCwgOCwgMCwgNSwgMSwgNCwgMiwgMywgNF1dLFxuICAgIFwiNlwiOiBbMjAsIFsxNiwgMTgsIDE1LCAyMCwgMTIsIDIxLCAxMCwgMjEsIDcsIDIwLCA1LCAxNywgNCwgMTIsIDQsIDcsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMSwgMCwgMTQsIDEsIDE2LCAzLCAxNywgNiwgMTcsIDcsIDE2LCAxMCwgMTQsIDEyLCAxMSwgMTMsIDEwLCAxMywgNywgMTIsIDUsIDEwLCA0LCA3XV0sXG4gICAgXCI3XCI6IFsyMCwgWzE3LCAyMSwgNywgMCwgLTEsIC0xLCAzLCAyMSwgMTcsIDIxXV0sXG4gICAgXCI4XCI6IFsyMCwgWzgsIDIxLCA1LCAyMCwgNCwgMTgsIDQsIDE2LCA1LCAxNCwgNywgMTMsIDExLCAxMiwgMTQsIDExLCAxNiwgOSwgMTcsIDcsIDE3LCA0LCAxNiwgMiwgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCA0LCAyLCAzLCA0LCAzLCA3LCA0LCA5LCA2LCAxMSwgOSwgMTIsIDEzLCAxMywgMTUsIDE0LCAxNiwgMTYsIDE2LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxXV0sXG4gICAgXCI5XCI6IFsyMCwgWzE2LCAxNCwgMTUsIDExLCAxMywgOSwgMTAsIDgsIDksIDgsIDYsIDksIDQsIDExLCAzLCAxNCwgMywgMTUsIDQsIDE4LCA2LCAyMCwgOSwgMjEsIDEwLCAyMSwgMTMsIDIwLCAxNSwgMTgsIDE2LCAxNCwgMTYsIDksIDE1LCA0LCAxMywgMSwgMTAsIDAsIDgsIDAsIDUsIDEsIDQsIDNdXSxcbiAgICBcIjpcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDUsIDIsIDQsIDEsIDUsIDAsIDYsIDEsIDUsIDJdXSxcbiAgICBcIjtcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDYsIDEsIDUsIDAsIDQsIDEsIDUsIDIsIDYsIDEsIDYsIC0xLCA1LCAtMywgNCwgLTRdXSxcbiAgICBcIjxcIjogWzI0LCBbMjAsIDE4LCA0LCA5LCAyMCwgMF1dLFxuICAgIFwiPVwiOiBbMjYsIFs0LCAxMiwgMjIsIDEyLCAtMSwgLTEsIDQsIDYsIDIyLCA2XV0sXG4gICAgXCI+XCI6IFsyNCwgWzQsIDE4LCAyMCwgOSwgNCwgMF1dLFxuICAgIFwiP1wiOiBbMTgsIFszLCAxNiwgMywgMTcsIDQsIDE5LCA1LCAyMCwgNywgMjEsIDExLCAyMSwgMTMsIDIwLCAxNCwgMTksIDE1LCAxNywgMTUsIDE1LCAxNCwgMTMsIDEzLCAxMiwgOSwgMTAsIDksIDcsIC0xLCAtMSwgOSwgMiwgOCwgMSwgOSwgMCwgMTAsIDEsIDksIDJdXSxcbiAgICBcIkBcIjogWzI3LCBbMTgsIDEzLCAxNywgMTUsIDE1LCAxNiwgMTIsIDE2LCAxMCwgMTUsIDksIDE0LCA4LCAxMSwgOCwgOCwgOSwgNiwgMTEsIDUsIDE0LCA1LCAxNiwgNiwgMTcsIDgsIC0xLCAtMSwgMTIsIDE2LCAxMCwgMTQsIDksIDExLCA5LCA4LCAxMCwgNiwgMTEsIDUsIC0xLCAtMSwgMTgsIDE2LCAxNywgOCwgMTcsIDYsIDE5LCA1LCAyMSwgNSwgMjMsIDcsIDI0LCAxMCwgMjQsIDEyLCAyMywgMTUsIDIyLCAxNywgMjAsIDE5LCAxOCwgMjAsIDE1LCAyMSwgMTIsIDIxLCA5LCAyMCwgNywgMTksIDUsIDE3LCA0LCAxNSwgMywgMTIsIDMsIDksIDQsIDYsIDUsIDQsIDcsIDIsIDksIDEsIDEyLCAwLCAxNSwgMCwgMTgsIDEsIDIwLCAyLCAyMSwgMywgLTEsIC0xLCAxOSwgMTYsIDE4LCA4LCAxOCwgNiwgMTksIDVdXSxcbiAgICBcIkFcIjogWzE4LCBbOSwgMjEsIDEsIDAsIC0xLCAtMSwgOSwgMjEsIDE3LCAwLCAtMSwgLTEsIDQsIDcsIDE0LCA3XV0sXG4gICAgXCJCXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgLTEsIC0xLCA0LCAxMSwgMTMsIDExLCAxNiwgMTAsIDE3LCA5LCAxOCwgNywgMTgsIDQsIDE3LCAyLCAxNiwgMSwgMTMsIDAsIDQsIDBdXSxcbiAgICBcIkNcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1XV0sXG4gICAgXCJEXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMSwgMjEsIDE0LCAyMCwgMTYsIDE4LCAxNywgMTYsIDE4LCAxMywgMTgsIDgsIDE3LCA1LCAxNiwgMywgMTQsIDEsIDExLCAwLCA0LCAwXV0sXG4gICAgXCJFXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxNywgMjEsIC0xLCAtMSwgNCwgMTEsIDEyLCAxMSwgLTEsIC0xLCA0LCAwLCAxNywgMF1dLFxuICAgIFwiRlwiOiBbMTgsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTcsIDIxLCAtMSwgLTEsIDQsIDExLCAxMiwgMTFdXSxcbiAgICBcIkdcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOCwgOCwgLTEsIC0xLCAxMywgOCwgMTgsIDhdXSxcbiAgICBcIkhcIjogWzIyLCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMCwgLTEsIC0xLCA0LCAxMSwgMTgsIDExXV0sXG4gICAgXCJJXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIkpcIjogWzE2LCBbMTIsIDIxLCAxMiwgNSwgMTEsIDIsIDEwLCAxLCA4LCAwLCA2LCAwLCA0LCAxLCAzLCAyLCAyLCA1LCAyLCA3XV0sXG4gICAgXCJLXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDE4LCAyMSwgNCwgNywgLTEsIC0xLCA5LCAxMiwgMTgsIDBdXSxcbiAgICBcIkxcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMCwgMTYsIDBdXSxcbiAgICBcIk1cIjogWzI0LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMjEsIDEyLCAwLCAtMSwgLTEsIDIwLCAyMSwgMTIsIDAsIC0xLCAtMSwgMjAsIDIxLCAyMCwgMF1dLFxuICAgIFwiTlwiOiBbMjIsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTgsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMF1dLFxuICAgIFwiT1wiOiBbMjIsIFs5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOSwgOCwgMTksIDEzLCAxOCwgMTYsIDE3LCAxOCwgMTUsIDIwLCAxMywgMjEsIDksIDIxXV0sXG4gICAgXCJQXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNCwgMTcsIDEyLCAxNiwgMTEsIDEzLCAxMCwgNCwgMTBdXSxcbiAgICBcIlFcIjogWzIyLCBbOSwgMjEsIDcsIDIwLCA1LCAxOCwgNCwgMTYsIDMsIDEzLCAzLCA4LCA0LCA1LCA1LCAzLCA3LCAxLCA5LCAwLCAxMywgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNSwgMTksIDgsIDE5LCAxMywgMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgLTEsIC0xLCAxMiwgNCwgMTgsIC0yXV0sXG4gICAgXCJSXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgNCwgMTEsIC0xLCAtMSwgMTEsIDExLCAxOCwgMF1dLFxuICAgIFwiU1wiOiBbMjAsIFsxNywgMTgsIDE1LCAyMCwgMTIsIDIxLCA4LCAyMSwgNSwgMjAsIDMsIDE4LCAzLCAxNiwgNCwgMTQsIDUsIDEzLCA3LCAxMiwgMTMsIDEwLCAxNSwgOSwgMTYsIDgsIDE3LCA2LCAxNywgMywgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCAzLCAzXV0sXG4gICAgXCJUXCI6IFsxNiwgWzgsIDIxLCA4LCAwLCAtMSwgLTEsIDEsIDIxLCAxNSwgMjFdXSxcbiAgICBcIlVcIjogWzIyLCBbNCwgMjEsIDQsIDYsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMiwgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNiwgMTgsIDIxXV0sXG4gICAgXCJWXCI6IFsxOCwgWzEsIDIxLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMF1dLFxuICAgIFwiV1wiOiBbMjQsIFsyLCAyMSwgNywgMCwgLTEsIC0xLCAxMiwgMjEsIDcsIDAsIC0xLCAtMSwgMTIsIDIxLCAxNywgMCwgLTEsIC0xLCAyMiwgMjEsIDE3LCAwXV0sXG4gICAgXCJYXCI6IFsyMCwgWzMsIDIxLCAxNywgMCwgLTEsIC0xLCAxNywgMjEsIDMsIDBdXSxcbiAgICBcIllcIjogWzE4LCBbMSwgMjEsIDksIDExLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMTFdXSxcbiAgICBcIlpcIjogWzIwLCBbMTcsIDIxLCAzLCAwLCAtMSwgLTEsIDMsIDIxLCAxNywgMjEsIC0xLCAtMSwgMywgMCwgMTcsIDBdXSxcbiAgICBcIltcIjogWzE0LCBbNCwgMjUsIDQsIC03LCAtMSwgLTEsIDUsIDI1LCA1LCAtNywgLTEsIC0xLCA0LCAyNSwgMTEsIDI1LCAtMSwgLTEsIDQsIC03LCAxMSwgLTddXSxcbiAgICBcIlxcXFxcIjogWzE0LCBbMCwgMjEsIDE0LCAtM11dLFxuICAgIFwiXVwiOiBbMTQsIFs5LCAyNSwgOSwgLTcsIC0xLCAtMSwgMTAsIDI1LCAxMCwgLTcsIC0xLCAtMSwgMywgMjUsIDEwLCAyNSwgLTEsIC0xLCAzLCAtNywgMTAsIC03XV0sXG4gICAgXCJeXCI6IFsxNiwgWzYsIDE1LCA4LCAxOCwgMTAsIDE1LCAtMSwgLTEsIDMsIDEyLCA4LCAxNywgMTMsIDEyLCAtMSwgLTEsIDgsIDE3LCA4LCAwXV0sXG4gICAgXCJfXCI6IFsxNiwgWzAsIC0yLCAxNiwgLTJdXSxcbiAgICBcImBcIjogWzEwLCBbNiwgMjEsIDUsIDIwLCA0LCAxOCwgNCwgMTYsIDUsIDE1LCA2LCAxNiwgNSwgMTddXSxcbiAgICBcImFcIjogWzE5LCBbMTUsIDE0LCAxNSwgMCwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJiXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDExLCA2LCAxMywgOCwgMTQsIDExLCAxNCwgMTMsIDEzLCAxNSwgMTEsIDE2LCA4LCAxNiwgNiwgMTUsIDMsIDEzLCAxLCAxMSwgMCwgOCwgMCwgNiwgMSwgNCwgM11dLFxuICAgIFwiY1wiOiBbMTgsIFsxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJkXCI6IFsxOSwgWzE1LCAyMSwgMTUsIDAsIC0xLCAtMSwgMTUsIDExLCAxMywgMTMsIDExLCAxNCwgOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgM11dLFxuICAgIFwiZVwiOiBbMTgsIFszLCA4LCAxNSwgOCwgMTUsIDEwLCAxNCwgMTIsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJmXCI6IFsxMiwgWzEwLCAyMSwgOCwgMjEsIDYsIDIwLCA1LCAxNywgNSwgMCwgLTEsIC0xLCAyLCAxNCwgOSwgMTRdXSxcbiAgICBcImdcIjogWzE5LCBbMTUsIDE0LCAxNSwgLTIsIDE0LCAtNSwgMTMsIC02LCAxMSwgLTcsIDgsIC03LCA2LCAtNiwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJoXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDEwLCA3LCAxMywgOSwgMTQsIDEyLCAxNCwgMTQsIDEzLCAxNSwgMTAsIDE1LCAwXV0sXG4gICAgXCJpXCI6IFs4LCBbMywgMjEsIDQsIDIwLCA1LCAyMSwgNCwgMjIsIDMsIDIxLCAtMSwgLTEsIDQsIDE0LCA0LCAwXV0sXG4gICAgXCJqXCI6IFsxMCwgWzUsIDIxLCA2LCAyMCwgNywgMjEsIDYsIDIyLCA1LCAyMSwgLTEsIC0xLCA2LCAxNCwgNiwgLTMsIDUsIC02LCAzLCAtNywgMSwgLTddXSxcbiAgICBcImtcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTQsIDE0LCA0LCA0LCAtMSwgLTEsIDgsIDgsIDE1LCAwXV0sXG4gICAgXCJsXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIm1cIjogWzMwLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDAsIC0xLCAtMSwgMTUsIDEwLCAxOCwgMTMsIDIwLCAxNCwgMjMsIDE0LCAyNSwgMTMsIDI2LCAxMCwgMjYsIDBdXSxcbiAgICBcIm5cIjogWzE5LCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDBdXSxcbiAgICBcIm9cIjogWzE5LCBbOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgMywgMTYsIDYsIDE2LCA4LCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNF1dLFxuICAgIFwicFwiOiBbMTksIFs0LCAxNCwgNCwgLTcsIC0xLCAtMSwgNCwgMTEsIDYsIDEzLCA4LCAxNCwgMTEsIDE0LCAxMywgMTMsIDE1LCAxMSwgMTYsIDgsIDE2LCA2LCAxNSwgMywgMTMsIDEsIDExLCAwLCA4LCAwLCA2LCAxLCA0LCAzXV0sXG4gICAgXCJxXCI6IFsxOSwgWzE1LCAxNCwgMTUsIC03LCAtMSwgLTEsIDE1LCAxMSwgMTMsIDEzLCAxMSwgMTQsIDgsIDE0LCA2LCAxMywgNCwgMTEsIDMsIDgsIDMsIDYsIDQsIDMsIDYsIDEsIDgsIDAsIDExLCAwLCAxMywgMSwgMTUsIDNdXSxcbiAgICBcInJcIjogWzEzLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgOCwgNSwgMTEsIDcsIDEzLCA5LCAxNCwgMTIsIDE0XV0sXG4gICAgXCJzXCI6IFsxNywgWzE0LCAxMSwgMTMsIDEzLCAxMCwgMTQsIDcsIDE0LCA0LCAxMywgMywgMTEsIDQsIDksIDYsIDgsIDExLCA3LCAxMywgNiwgMTQsIDQsIDE0LCAzLCAxMywgMSwgMTAsIDAsIDcsIDAsIDQsIDEsIDMsIDNdXSxcbiAgICBcInRcIjogWzEyLCBbNSwgMjEsIDUsIDQsIDYsIDEsIDgsIDAsIDEwLCAwLCAtMSwgLTEsIDIsIDE0LCA5LCAxNF1dLFxuICAgIFwidVwiOiBbMTksIFs0LCAxNCwgNCwgNCwgNSwgMSwgNywgMCwgMTAsIDAsIDEyLCAxLCAxNSwgNCwgLTEsIC0xLCAxNSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ2XCI6IFsxNiwgWzIsIDE0LCA4LCAwLCAtMSwgLTEsIDE0LCAxNCwgOCwgMF1dLFxuICAgIFwid1wiOiBbMjIsIFszLCAxNCwgNywgMCwgLTEsIC0xLCAxMSwgMTQsIDcsIDAsIC0xLCAtMSwgMTEsIDE0LCAxNSwgMCwgLTEsIC0xLCAxOSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ4XCI6IFsxNywgWzMsIDE0LCAxNCwgMCwgLTEsIC0xLCAxNCwgMTQsIDMsIDBdXSxcbiAgICBcInlcIjogWzE2LCBbMiwgMTQsIDgsIDAsIC0xLCAtMSwgMTQsIDE0LCA4LCAwLCA2LCAtNCwgNCwgLTYsIDIsIC03LCAxLCAtN11dLFxuICAgIFwielwiOiBbMTcsIFsxNCwgMTQsIDMsIDAsIC0xLCAtMSwgMywgMTQsIDE0LCAxNCwgLTEsIC0xLCAzLCAwLCAxNCwgMF1dLFxuICAgIFwie1wiOiBbMTQsIFs5LCAyNSwgNywgMjQsIDYsIDIzLCA1LCAyMSwgNSwgMTksIDYsIDE3LCA3LCAxNiwgOCwgMTQsIDgsIDEyLCA2LCAxMCwgLTEsIC0xLCA3LCAyNCwgNiwgMjIsIDYsIDIwLCA3LCAxOCwgOCwgMTcsIDksIDE1LCA5LCAxMywgOCwgMTEsIDQsIDksIDgsIDcsIDksIDUsIDksIDMsIDgsIDEsIDcsIDAsIDYsIC0yLCA2LCAtNCwgNywgLTYsIC0xLCAtMSwgNiwgOCwgOCwgNiwgOCwgNCwgNywgMiwgNiwgMSwgNSwgLTEsIDUsIC0zLCA2LCAtNSwgNywgLTYsIDksIC03XV0sXG4gICAgXCJ8XCI6IFs4LCBbNCwgMjUsIDQsIC03XV0sXG4gICAgXCJ9XCI6IFsxNCwgWzUsIDI1LCA3LCAyNCwgOCwgMjMsIDksIDIxLCA5LCAxOSwgOCwgMTcsIDcsIDE2LCA2LCAxNCwgNiwgMTIsIDgsIDEwLCAtMSwgLTEsIDcsIDI0LCA4LCAyMiwgOCwgMjAsIDcsIDE4LCA2LCAxNywgNSwgMTUsIDUsIDEzLCA2LCAxMSwgMTAsIDksIDYsIDcsIDUsIDUsIDUsIDMsIDYsIDEsIDcsIDAsIDgsIC0yLCA4LCAtNCwgNywgLTYsIC0xLCAtMSwgOCwgOCwgNiwgNiwgNiwgNCwgNywgMiwgOCwgMSwgOSwgLTEsIDksIC0zLCA4LCAtNSwgNywgLTYsIDUsIC03XV0sXG4gICAgXCJ+XCI6IFsyNCwgWzMsIDYsIDMsIDgsIDQsIDExLCA2LCAxMiwgOCwgMTIsIDEwLCAxMSwgMTQsIDgsIDE2LCA3LCAxOCwgNywgMjAsIDgsIDIxLCAxMCwgLTEsIC0xLCAzLCA4LCA0LCAxMCwgNiwgMTEsIDgsIDExLCAxMCwgMTAsIDE0LCA3LCAxNiwgNiwgMTgsIDYsIDIwLCA3LCAyMSwgMTAsIDIxLCAxMl1dXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRleHRWZXJ0aWNlcyh0ZXh0LCBsZWZ0LCBiYXNlbGluZSwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDE7XG5cbiAgICB2YXIgc3Ryb2tlcyA9IFtdLFxuICAgICAgICBpLCBsZW4sIGosIGxlbjIsIGdseXBoLCB4LCB5LCBwcmV2O1xuXG4gICAgZm9yIChpID0gMCwgbGVuID0gdGV4dC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBnbHlwaCA9IHNpbXBsZXhGb250W3RleHRbaV1dO1xuICAgICAgICBpZiAoIWdseXBoKSBjb250aW51ZTtcbiAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgZm9yIChqID0gMCwgbGVuMiA9IGdseXBoWzFdLmxlbmd0aDsgaiA8IGxlbjI7IGogKz0gMikge1xuICAgICAgICAgICAgaWYgKGdseXBoWzFdW2pdID09PSAtMSAmJiBnbHlwaFsxXVtqICsgMV0gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeCA9IGxlZnQgKyBnbHlwaFsxXVtqXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIHkgPSBiYXNlbGluZSAtIGdseXBoWzFdW2ogKyAxXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZXMucHVzaChwcmV2LngsIHByZXYueSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXYgPSB7eDogeCwgeTogeX07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGVmdCArPSBnbHlwaFswXSAqIHNjYWxlO1xuICAgIH1cblxuICAgIHJldHVybiBzdHJva2VzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBtYXBib3hnbCBpcyBhIEEgV2ViR0wgSmF2YVNjcmlwdCBpbnRlcmFjdGl2ZSBtYXBzIGxpYnJhcnkgdGhhdCBjYW4gcmVuZGVyXG4gKiBbTWFwYm94IHZlY3RvciB0aWxlc10oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9ibG9nL3ZlY3Rvci10aWxlcy8pLlxuICpcbiAqIEBtb2R1bGUgbWFwYm94Z2xcbiAqIEBzdW1tYXJ5IFdlYkdMIEphdmFTY3JpcHQgbWFwIGxpYnJhcnlcbiAqL1xuXG4vLyBqc2hpbnQgLVcwNzlcbnZhciBtYXBib3hnbCA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbm1hcGJveGdsLk1hcCA9IHJlcXVpcmUoJy4vdWkvbWFwJyk7XG5tYXBib3hnbC5OYXZpZ2F0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL25hdmlnYXRpb24nKTtcbm1hcGJveGdsLkF0dHJpYnV0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL2F0dHJpYnV0aW9uJyk7XG5tYXBib3hnbC5Qb3B1cCA9IHJlcXVpcmUoJy4vdWkvcG9wdXAnKTtcblxubWFwYm94Z2wuR2VvSlNPTlNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL2dlb2pzb25fc291cmNlJyk7XG5tYXBib3hnbC5WaWRlb1NvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL3ZpZGVvX3NvdXJjZScpO1xuXG5tYXBib3hnbC5TdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUvc3R5bGUnKTtcblxubWFwYm94Z2wuTGF0TG5nID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZycpO1xubWFwYm94Z2wuTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbm1hcGJveGdsLlBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubWFwYm94Z2wuRXZlbnRlZCA9IHJlcXVpcmUoJy4vdXRpbC9ldmVudGVkJyk7XG5tYXBib3hnbC51dGlsID0gcmVxdWlyZSgnLi91dGlsL3V0aWwnKTtcblxubWFwYm94Z2wuc3VwcG9ydGVkID0gcmVxdWlyZSgnLi91dGlsL2Jyb3dzZXInKS5zdXBwb3J0ZWQ7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi91dGlsL2FqYXgnKTtcbm1hcGJveGdsLnV0aWwuZ2V0SlNPTiA9IGFqYXguZ2V0SlNPTjtcbm1hcGJveGdsLnV0aWwuZ2V0QXJyYXlCdWZmZXIgPSBhamF4LmdldEFycmF5QnVmZmVyO1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi91dGlsL2NvbmZpZycpO1xubWFwYm94Z2wuY29uZmlnID0gY29uZmlnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWFwYm94Z2wsICdhY2Nlc3NUb2tlbicsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnLkFDQ0VTU19UT0tFTjsgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHRva2VuKSB7IGNvbmZpZy5BQ0NFU1NfVE9LRU4gPSB0b2tlbjsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBtYXQzID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0MztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3QmFja2dyb3VuZDtcblxuZnVuY3Rpb24gZHJhd0JhY2tncm91bmQocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtY29sb3InXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnYmFja2dyb3VuZC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtb3BhY2l0eSddO1xuICAgIHZhciBzaGFkZXI7XG5cbiAgICB2YXIgaW1hZ2VQb3NBID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpIDogbnVsbDtcbiAgICB2YXIgaW1hZ2VQb3NCID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLnRvLCB0cnVlKSA6IG51bGw7XG5cbiAgICBpZiAoaW1hZ2VQb3NBICYmIGltYWdlUG9zQikge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZSwgMCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9hLCBpbWFnZVBvc0EudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYSwgaW1hZ2VQb3NBLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2IsIGltYWdlUG9zQi50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9iLCBpbWFnZVBvc0IuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eSwgb3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgICAgICB2YXIgc2l6ZUEgPSBpbWFnZVBvc0Euc2l6ZTtcbiAgICAgICAgdmFyIHNpemVCID0gaW1hZ2VQb3NCLnNpemU7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0cmFuc2Zvcm0ubG9jYXRpb25Db29yZGluYXRlKHRyYW5zZm9ybS5jZW50ZXIpO1xuICAgICAgICB2YXIgc2NhbGUgPSAxIC8gTWF0aC5wb3coMiwgdHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21peCwgaW1hZ2UudCk7XG5cbiAgICAgICAgdmFyIG1hdHJpeEEgPSBtYXQzLmNyZWF0ZSgpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIDEgLyAoc2l6ZUFbMF0gKiBpbWFnZS5mcm9tU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQVsxXSAqIGltYWdlLmZyb21TY2FsZSlcbiAgICAgICAgXSk7XG4gICAgICAgIG1hdDMudHJhbnNsYXRlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIChjZW50ZXIuY29sdW1uICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQVswXSAqIGltYWdlLmZyb21TY2FsZSksXG4gICAgICAgICAgICAoY2VudGVyLnJvdyAgICAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUFbMV0gKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhBLCBtYXRyaXhBLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICB2YXIgbWF0cml4QiA9IG1hdDMuY3JlYXRlKCk7XG4gICAgICAgIG1hdDMuc2NhbGUobWF0cml4QiwgbWF0cml4QiwgW1xuICAgICAgICAgICAgMSAvIChzaXplQlswXSAqIGltYWdlLnRvU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnRyYW5zbGF0ZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAoY2VudGVyLmNvbHVtbiAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUJbMF0gKiBpbWFnZS50b1NjYWxlKSxcbiAgICAgICAgICAgIChjZW50ZXIucm93ICAgICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhCLCBtYXRyaXhCLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYSwgZmFsc2UsIG1hdHJpeEEpO1xuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYiwgZmFsc2UsIG1hdHJpeEIpO1xuXG4gICAgICAgIHBhaW50ZXIuc3ByaXRlQXRsYXMuYmluZChnbCwgdHJ1ZSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEcmF3IGZpbGxpbmcgcmVjdGFuZ2xlLlxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmZpbGxTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm00ZnYoc2hhZGVyLnVfY29sb3IsIGNvbG9yKTtcbiAgICB9XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIuaXRlbUNvdW50KTtcbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcblxuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3UGxhY2VtZW50RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdQbGFjZW1lbnREZWJ1ZyhwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlKSB7XG5cbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdLmNvbGxpc2lvbkJveDtcbiAgICBpZiAoIWVsZW1lbnRHcm91cHMpIHJldHVybjtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGJ1ZmZlciA9IHRpbGUuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIHNoYWRlciA9IHBhaW50ZXIuY29sbGlzaW9uQm94U2hhZGVyO1xuXG4gICAgZ2wuZW5hYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgIGJ1ZmZlci5iaW5kKGdsLCBzaGFkZXIpO1xuICAgIGdsLmxpbmVXaWR0aCgzKTtcblxuICAgIHZhciBzdHJpZGUgPSAxMjtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZXh0cnVkZSwgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDQpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YSwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgOCk7XG5cbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2NhbGUsIE1hdGgucG93KDIsIHBhaW50ZXIudHJhbnNmb3JtLnpvb20gLSB0aWxlLmNvb3JkLnopKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfem9vbSwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWF4em9vbSwgKHRpbGUuY29vcmQueiArIDEpICogMTApO1xuXG4gICAgdmFyIGJlZ2luID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4U3RhcnRJbmRleDtcbiAgICB2YXIgbGVuID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4TGVuZ3RoO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIGJlZ2luLCBsZW4pO1xuXG4gICAgZ2wuZGlzYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdGV4dFZlcnRpY2VzID0gcmVxdWlyZSgnLi4vbGliL2RlYnVndGV4dCcpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdEZWJ1ZyhwYWludGVyLCB0aWxlKSB7XG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcblxuICAgIC8vIEJsZW5kIHRvIHRoZSBmcm9udCwgbm90IHRoZSBiYWNrLlxuICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZGVidWdTaGFkZXIsIHRpbGUucG9zTWF0cml4KTtcblxuICAgIC8vIGRyYXcgYm91bmRpbmcgcmVjdGFuZ2xlXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuZGVidWdCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z0J1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC51bmlmb3JtNGYocGFpbnRlci5kZWJ1Z1NoYWRlci51X2NvbG9yLCAxLCAwLCAwLCAxKTtcbiAgICBnbC5saW5lV2lkdGgoNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FX1NUUklQLCAwLCBwYWludGVyLmRlYnVnQnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICB2YXIgdmVydGljZXMgPSB0ZXh0VmVydGljZXModGlsZS5jb29yZC50b1N0cmluZygpLCA1MCwgMjAwLCA1KTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmRlYnVnVGV4dEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KHZlcnRpY2VzKSwgZ2wuU1RSRUFNX0RSQVcpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wubGluZVdpZHRoKDggKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDEsIDEsIDEpO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHZlcnRpY2VzLmxlbmd0aCAvIHBhaW50ZXIuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplKTtcbiAgICBnbC5saW5lV2lkdGgoMiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgZ2wudW5pZm9ybTRmKHBhaW50ZXIuZGVidWdTaGFkZXIudV9jb2xvciwgMCwgMCwgMCwgMSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdmVydGljZXMubGVuZ3RoIC8gcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0MyA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDM7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0ZpbGw7XG5cbmZ1bmN0aW9uIGRyYXdGaWxsKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpIHtcbiAgICAvLyBObyBkYXRhXG4gICAgaWYgKCF0aWxlLmJ1ZmZlcnMpIHJldHVybjtcbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdO1xuICAgIGlmICghZWxlbWVudEdyb3VwcykgcmV0dXJuO1xuXG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcbiAgICB2YXIgdHJhbnNsYXRlZFBvc01hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2ZpbGwtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydmaWxsLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgY29sb3IgPSBsYXllci5wYWludFsnZmlsbC1jb2xvciddO1xuXG4gICAgdmFyIHZlcnRleCwgZWxlbWVudHMsIGdyb3VwLCBjb3VudDtcblxuICAgIC8vIERyYXcgdGhlIHN0ZW5jaWwgbWFzay5cblxuICAgIC8vIFdlJ3JlIG9ubHkgZHJhd2luZyB0byB0aGUgZmlyc3Qgc2V2ZW4gYml0cyAoPT0gc3VwcG9ydCBhIG1heGltdW0gb2ZcbiAgICAvLyAxMjcgb3ZlcmxhcHBpbmcgcG9seWdvbnMgaW4gb25lIHBsYWNlIGJlZm9yZSB3ZSBnZXQgcmVuZGVyaW5nIGVycm9ycykuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgzRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIERyYXcgZnJvbnQgZmFjaW5nIHRyaWFuZ2xlcy4gV2hlcmV2ZXIgdGhlIDB4ODAgYml0IGlzIDEsIHdlIGFyZVxuICAgIC8vIGluY3JlYXNpbmcgdGhlIGxvd2VyIDcgYml0cyBieSBvbmUgaWYgdGhlIHRyaWFuZ2xlIGlzIGEgZnJvbnQtZmFjaW5nXG4gICAgLy8gdHJpYW5nbGUuIFRoaXMgbWVhbnMgdGhhdCBhbGwgdmlzaWJsZSBwb2x5Z29ucyBzaG91bGQgYmUgaW4gQ0NXXG4gICAgLy8gb3JpZW50YXRpb24sIHdoaWxlIGFsbCBob2xlcyAoc2VlIGJlbG93KSBhcmUgaW4gQ1cgb3JpZW50YXRpb24uXG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuTk9URVFVQUwsIDB4ODAsIDB4ODApO1xuXG4gICAgLy8gV2hlbiB3ZSBkbyBhIG5vbnplcm8gZmlsbCwgd2UgY291bnQgdGhlIG51bWJlciBvZiB0aW1lcyBhIHBpeGVsIGlzXG4gICAgLy8gY292ZXJlZCBieSBhIGNvdW50ZXJjbG9ja3dpc2UgcG9seWdvbiwgYW5kIHN1YnRyYWN0IHRoZSBudW1iZXIgb2ZcbiAgICAvLyB0aW1lcyBpdCBpcyBcInVuY292ZXJlZFwiIGJ5IGEgY2xvY2t3aXNlIHBvbHlnb24uXG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuRlJPTlQsIGdsLklOQ1JfV1JBUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuQkFDSywgZ2wuREVDUl9XUkFQLCBnbC5LRUVQLCBnbC5LRUVQKTtcblxuICAgIC8vIFdoZW4gZHJhd2luZyBhIHNoYXBlLCB3ZSBmaXJzdCBkcmF3IGFsbCBzaGFwZXMgdG8gdGhlIHN0ZW5jaWwgYnVmZmVyXG4gICAgLy8gYW5kIGluY3JlbWVudGluZyBhbGwgYXJlYXMgd2hlcmUgcG9seWdvbnMgYXJlXG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIERyYXcgdGhlIGFjdHVhbCB0cmlhbmdsZSBmYW4gaW50byB0aGUgc3RlbmNpbCBidWZmZXIuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZmlsbFNoYWRlciwgdHJhbnNsYXRlZFBvc01hdHJpeCk7XG5cbiAgICAvLyBEcmF3IGFsbCBidWZmZXJzXG4gICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIGVsZW1lbnRzLmJpbmQoZ2wpO1xuXG4gICAgdmFyIG9mZnNldCwgZWxlbWVudE9mZnNldDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmZpbGxTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgNCwgb2Zmc2V0ICsgMCk7XG5cbiAgICAgICAgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgc3RlbmNpbCBtYXNrIGluIHRoZSBzdGVuY2lsIGJ1ZmZlciwgd2UgY2FuIHN0YXJ0XG4gICAgLy8gd3JpdGluZyB0byB0aGUgY29sb3IgYnVmZmVyLlxuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcblxuICAgIC8vIEZyb20gbm93IG9uLCB3ZSBkb24ndCB3YW50IHRvIHVwZGF0ZSB0aGUgc3RlbmNpbCBidWZmZXIgYW55bW9yZS5cbiAgICBnbC5zdGVuY2lsT3AoZ2wuS0VFUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwKTtcblxuICAgIHZhciBzdHJva2VDb2xvciA9IGxheWVyLnBhaW50WydmaWxsLW91dGxpbmUtY29sb3InXTtcblxuICAgIC8vIEJlY2F1c2Ugd2UncmUgZHJhd2luZyB0b3AtdG8tYm90dG9tLCBhbmQgd2UgdXBkYXRlIHRoZSBzdGVuY2lsIG1hc2tcbiAgICAvLyBiZWxvdywgd2UgaGF2ZSB0byBkcmF3IHRoZSBvdXRsaW5lIGZpcnN0ICghKVxuICAgIGlmIChsYXllci5wYWludFsnZmlsbC1hbnRpYWxpYXMnXSA9PT0gdHJ1ZSAmJiAhKGxheWVyLnBhaW50WydmaWxsLWltYWdlJ10gJiYgIXN0cm9rZUNvbG9yKSkge1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLCB0cmFuc2xhdGVkUG9zTWF0cml4KTtcbiAgICAgICAgZ2wubGluZVdpZHRoKDIgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuXG4gICAgICAgIGlmIChzdHJva2VDb2xvcikge1xuICAgICAgICAgICAgLy8gSWYgd2UgZGVmaW5lZCBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGZpbGwgb3V0bGluZSwgd2UgYXJlXG4gICAgICAgICAgICAvLyBnb2luZyB0byBpZ25vcmUgdGhlIGJpdHMgaW4gMHgzRiBhbmQganVzdCBjYXJlIGFib3V0IHRoZSBnbG9iYWxcbiAgICAgICAgICAgIC8vIGNsaXBwaW5nIG1hc2suXG4gICAgICAgICAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIG9ubHkgd2FudCB0byBkcmF3IHRoZSBhbnRpYWxpYXNlZCBwYXJ0cyB0aGF0IGFyZVxuICAgICAgICAgICAgLy8gKm91dHNpZGUqIHRoZSBjdXJyZW50IHNoYXBlLiBUaGlzIGlzIGltcG9ydGFudCBpbiBjYXNlIHRoZSBmaWxsXG4gICAgICAgICAgICAvLyBvciBzdHJva2UgY29sb3IgaXMgdHJhbnNsdWNlbnQuIElmIHdlIHdvdWxkbid0IGNsaXAgdG8gb3V0c2lkZVxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2hhcGUsIHNvbWUgcGl4ZWxzIGZyb20gdGhlIG91dGxpbmUgc3Ryb2tlIG92ZXJsYXBwZWRcbiAgICAgICAgICAgIC8vIHRoZSAobm9uLWFudGlhbGlhc2VkKSBmaWxsLlxuICAgICAgICAgICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4QkYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmKHBhaW50ZXIub3V0bGluZVNoYWRlci51X3dvcmxkLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHBhaW50ZXIub3V0bGluZVNoYWRlci51X2NvbG9yLCBzdHJva2VDb2xvciA/IHN0cm9rZUNvbG9yIDogY29sb3IpO1xuXG4gICAgICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICAgICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLm91dGxpbmVFbGVtZW50O1xuICAgICAgICBlbGVtZW50cy5iaW5kKGdsKTtcblxuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDQsIG9mZnNldCArIDApO1xuXG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGggKiAyO1xuICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICBnbC5kcmF3RWxlbWVudHMoZ2wuTElORVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnZmlsbC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2ZpbGwtb3BhY2l0eSddIHx8IDE7XG4gICAgdmFyIHNoYWRlcjtcblxuICAgIGlmIChpbWFnZSkge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICB2YXIgaW1hZ2VQb3NBID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS5mcm9tLCB0cnVlKTtcbiAgICAgICAgdmFyIGltYWdlUG9zQiA9IHBhaW50ZXIuc3ByaXRlQXRsYXMuZ2V0UG9zaXRpb24oaW1hZ2UudG8sIHRydWUpO1xuICAgICAgICBpZiAoIWltYWdlUG9zQSB8fCAhaW1hZ2VQb3NCKSByZXR1cm47XG5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5wYXR0ZXJuU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtMWkoc2hhZGVyLnVfaW1hZ2UsIDApO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYSwgaW1hZ2VQb3NBLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2EsIGltYWdlUG9zQS5icik7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9iLCBpbWFnZVBvc0IudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYiwgaW1hZ2VQb3NCLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIG9wYWNpdHkpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBpbWFnZS50KTtcblxuICAgICAgICB2YXIgZmFjdG9yID0gKHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUpIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gLSB0aWxlLmNvb3JkLnopO1xuXG4gICAgICAgIHZhciBtYXRyaXhBID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQS5zaXplWzBdICogZmFjdG9yICogaW1hZ2UuZnJvbVNjYWxlKSxcbiAgICAgICAgICAgIDEgLyAoaW1hZ2VQb3NBLnNpemVbMV0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHZhciBtYXRyaXhCID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzBdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSksXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzFdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSlcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2EsIGZhbHNlLCBtYXRyaXhBKTtcbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2IsIGZhbHNlLCBtYXRyaXhCKTtcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRHJhdyBmaWxsaW5nIHJlY3RhbmdsZS5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5maWxsU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgLy8gT25seSBkcmF3IHJlZ2lvbnMgdGhhdCB3ZSBtYXJrZWRcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHgwLCAweDNGKTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4ODApO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDIgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQyO1xuXG4vKipcbiAqIERyYXcgYSBsaW5lLiBVbmRlciB0aGUgaG9vZCB0aGlzIHdpbGwgcmVhZCBlbGVtZW50cyBmcm9tXG4gKiBhIHRpbGUsIGRhc2ggdGV4dHVyZXMgZnJvbSBhIGxpbmVBdGxhcywgYW5kIHN0eWxlIHByb3BlcnRpZXMgZnJvbSBhIGxheWVyLlxuICogQHBhcmFtIHtPYmplY3R9IHBhaW50ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXllclxuICogQHBhcmFtIHtPYmplY3R9IHBvc01hdHJpeFxuICogQHBhcmFtIHtUaWxlfSB0aWxlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBkcmF3cyB3aXRoIHRoZSBwYWludGVyXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhd0xpbmUocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuXG4gICAgLy8gZG9uJ3QgZHJhdyB6ZXJvLXdpZHRoIGxpbmVzXG4gICAgaWYgKGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ10gPD0gMCkgcmV0dXJuO1xuXG4gICAgLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXG4gICAgLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXG4gICAgdmFyIGFudGlhbGlhc2luZyA9IDEgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICB2YXIgYmx1ciA9IGxheWVyLnBhaW50WydsaW5lLWJsdXInXSArIGFudGlhbGlhc2luZztcbiAgICB2YXIgZWRnZVdpZHRoID0gbGF5ZXIucGFpbnRbJ2xpbmUtd2lkdGgnXSAvIDI7XG4gICAgdmFyIGluc2V0ID0gLTE7XG4gICAgdmFyIG9mZnNldCA9IDA7XG4gICAgdmFyIHNoaWZ0ID0gMDtcblxuICAgIGlmIChsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSA+IDApIHtcbiAgICAgICAgaW5zZXQgPSBsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSAvIDIgKyBhbnRpYWxpYXNpbmcgKiAwLjU7XG4gICAgICAgIGVkZ2VXaWR0aCA9IGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ107XG5cbiAgICAgICAgLy8gc2hpZnQgb3V0ZXIgbGluZXMgaGFsZiBhIHBpeGVsIHRvd2FyZHMgdGhlIG1pZGRsZSB0byBlbGltaW5hdGUgdGhlIGNyYWNrXG4gICAgICAgIG9mZnNldCA9IGluc2V0IC0gYW50aWFsaWFzaW5nIC8gMjtcbiAgICB9XG5cbiAgICB2YXIgb3V0c2V0ID0gb2Zmc2V0ICsgZWRnZVdpZHRoICsgYW50aWFsaWFzaW5nIC8gMiArIHNoaWZ0O1xuXG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2xpbmUtY29sb3InXTtcbiAgICB2YXIgcmF0aW8gPSBwYWludGVyLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHZ0eE1hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2xpbmUtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydsaW5lLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgdHIgPSBwYWludGVyLnRyYW5zZm9ybTtcblxuXG4gICAgdmFyIGFudGlhbGlhc2luZ01hdHJpeCA9IG1hdDIuY3JlYXRlKCk7XG4gICAgbWF0Mi5zY2FsZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgWzEsIE1hdGguY29zKHRyLl9waXRjaCldKTtcbiAgICBtYXQyLnJvdGF0ZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgcGFpbnRlci50cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIGxvbmdlciB0aGUgcmVhbCB3b3JsZCBkaXN0YW5jZSBpcyBhdCB0aGUgdG9wIG9mIHRoZSBzY3JlZW5cbiAgICAvLyB0aGFuIGF0IHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbi5cbiAgICB2YXIgdG9wZWRnZWxlbmd0aCA9IE1hdGguc3FydCh0ci5oZWlnaHQgKiB0ci5oZWlnaHQgLyA0ICAqICgxICsgdHIuYWx0aXR1ZGUgKiB0ci5hbHRpdHVkZSkpO1xuICAgIHZhciB4ID0gdHIuaGVpZ2h0IC8gMiAqIE1hdGgudGFuKHRyLl9waXRjaCk7XG4gICAgdmFyIGV4dHJhID0gKHRvcGVkZ2VsZW5ndGggKyB4KSAvIHRvcGVkZ2VsZW5ndGggLSAxO1xuXG4gICAgLy8gaG93IG11Y2ggdGhlIHRpbGUgaXMgb3ZlcnNjYWxlZCBieVxuICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUudGlsZVNpemUgLyBwYWludGVyLnRyYW5zZm9ybS50aWxlU2l6ZTtcblxuICAgIHZhciBzaGFkZXI7XG5cblxuICAgIHZhciBkYXNoYXJyYXkgPSBsYXllci5wYWludFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnbGluZS1pbWFnZSddO1xuXG4gICAgaWYgKGRhc2hhcnJheSkge1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXNkZnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgY29sb3IpO1xuXG4gICAgICAgIHZhciBwb3NBID0gcGFpbnRlci5saW5lQXRsYXMuZ2V0RGFzaChkYXNoYXJyYXkuZnJvbSwgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgdmFyIHBvc0IgPSBwYWludGVyLmxpbmVBdGxhcy5nZXREYXNoKGRhc2hhcnJheS50bywgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgcGFpbnRlci5saW5lQXRsYXMuYmluZChnbCk7XG5cbiAgICAgICAgdmFyIHBhdHRlcm5yYXRpbyA9IE1hdGgucG93KDIsIE1hdGguZmxvb3IoTWF0aC5sb2cocGFpbnRlci50cmFuc2Zvcm0uc2NhbGUpIC8gTWF0aC5MTjIpIC0gdGlsZS5jb29yZC56KSAvIDggKiBvdmVyc2NhbGluZztcbiAgICAgICAgdmFyIHNjYWxlQSA9IFtwYXR0ZXJucmF0aW8gLyBwb3NBLndpZHRoIC8gZGFzaGFycmF5LmZyb21TY2FsZSwgLXBvc0EuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUEgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkuZnJvbVNjYWxlICogcG9zQS53aWR0aCAqIDI1NiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbykgLyAyO1xuICAgICAgICB2YXIgc2NhbGVCID0gW3BhdHRlcm5yYXRpbyAvIHBvc0Iud2lkdGggLyBkYXNoYXJyYXkudG9TY2FsZSwgLXBvc0IuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUIgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkudG9TY2FsZSAqIHBvc0Iud2lkdGggKiAyNTYgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pIC8gMjtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5zY2FsZV9hLCBzY2FsZUEpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfdGV4X3lfYSwgcG9zQS55KTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuc2NhbGVfYiwgc2NhbGVCKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3RleF95X2IsIHBvc0IueSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlLCAwKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NkZmdhbW1hLCBNYXRoLm1heChnYW1tYUEsIGdhbW1hQikpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBkYXNoYXJyYXkudCk7XG5cbiAgICB9IGVsc2UgaWYgKGltYWdlKSB7XG4gICAgICAgIHZhciBpbWFnZVBvc0EgPSBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpO1xuICAgICAgICB2YXIgaW1hZ2VQb3NCID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS50bywgdHJ1ZSk7XG4gICAgICAgIGlmICghaW1hZ2VQb3NBIHx8ICFpbWFnZVBvc0IpIHJldHVybjtcbiAgICAgICAgdmFyIGZhY3RvciA9IHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUgLyBNYXRoLnBvdygyLCBwYWludGVyLnRyYW5zZm9ybS50aWxlWm9vbSAtIHRpbGUuY29vcmQueikgKiBvdmVyc2NhbGluZztcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9hLCBbaW1hZ2VQb3NBLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUsIGltYWdlUG9zQi5zaXplWzFdIF0pO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9iLCBbaW1hZ2VQb3NCLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS50b1NjYWxlLCBpbWFnZVBvc0Iuc2l6ZVsxXSBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2EsIGltYWdlUG9zQS50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9hLCBpbWFnZVBvc0EuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYiwgaW1hZ2VQb3NCLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2IsIGltYWdlUG9zQi5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlLCBpbWFnZS50KTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIGxheWVyLnBhaW50WydsaW5lLW9wYWNpdHknXSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmxpbmVTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2V4dHJhLCBleHRyYSk7XG4gICAgICAgIGdsLnVuaWZvcm1NYXRyaXgyZnYoc2hhZGVyLnVfYW50aWFsaWFzaW5nbWF0cml4LCBmYWxzZSwgYW50aWFsaWFzaW5nTWF0cml4KTtcblxuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgdmFyIHZlcnRleCA9IHRpbGUuYnVmZmVycy5saW5lVmVydGV4O1xuICAgIHZlcnRleC5iaW5kKGdsKTtcbiAgICB2YXIgZWxlbWVudCA9IHRpbGUuYnVmZmVycy5saW5lRWxlbWVudDtcbiAgICBlbGVtZW50LmJpbmQoZ2wpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50R3JvdXBzLmdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHZ0eE9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIHZ0eE9mZnNldCArIDApO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGEsIDQsIGdsLkJZVEUsIGZhbHNlLCA4LCB2dHhPZmZzZXQgKyA0KTtcblxuICAgICAgICB2YXIgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgdmFyIGVsZW1lbnRPZmZzZXQgPSBncm91cC5lbGVtZW50U3RhcnRJbmRleCAqIGVsZW1lbnQuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdSYXN0ZXI7XG5cbmZ1bmN0aW9uIGRyYXdSYXN0ZXIocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICB2YXIgc2hhZGVyID0gcGFpbnRlci5yYXN0ZXJTaGFkZXI7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4KTtcblxuICAgIC8vIGNvbG9yIHBhcmFtZXRlcnNcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnJpZ2h0bmVzc19sb3csIGxheWVyLnBhaW50WydyYXN0ZXItYnJpZ2h0bmVzcy1taW4nXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2JyaWdodG5lc3NfaGlnaCwgbGF5ZXIucGFpbnRbJ3Jhc3Rlci1icmlnaHRuZXNzLW1heCddKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2F0dXJhdGlvbl9mYWN0b3IsIHNhdHVyYXRpb25GYWN0b3IobGF5ZXIucGFpbnRbJ3Jhc3Rlci1zYXR1cmF0aW9uJ10pKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfY29udHJhc3RfZmFjdG9yLCBjb250cmFzdEZhY3RvcihsYXllci5wYWludFsncmFzdGVyLWNvbnRyYXN0J10pKTtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlci51X3NwaW5fd2VpZ2h0cywgc3BpbldlaWdodHMobGF5ZXIucGFpbnRbJ3Jhc3Rlci1odWUtcm90YXRlJ10pKTtcblxuICAgIHZhciBwYXJlbnRUaWxlID0gdGlsZS5zb3VyY2UgJiYgdGlsZS5zb3VyY2UuX3B5cmFtaWQuZmluZExvYWRlZFBhcmVudCh0aWxlLmNvb3JkLCAwLCB7fSksXG4gICAgICAgIG9wYWNpdGllcyA9IGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgcGFpbnRlci50cmFuc2Zvcm0pO1xuXG4gICAgdmFyIHBhcmVudFNjYWxlQnksIHBhcmVudFRMO1xuXG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcblxuICAgIGlmIChwYXJlbnRUaWxlKSB7XG4gICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTEpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBwYXJlbnRUaWxlLnRleHR1cmUpO1xuXG4gICAgICAgIHBhcmVudFNjYWxlQnkgPSBNYXRoLnBvdygyLCBwYXJlbnRUaWxlLmNvb3JkLnogLSB0aWxlLmNvb3JkLnopO1xuICAgICAgICBwYXJlbnRUTCA9IFt0aWxlLmNvb3JkLnggKiBwYXJlbnRTY2FsZUJ5ICUgMSwgdGlsZS5jb29yZC55ICogcGFyZW50U2NhbGVCeSAlIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wYWNpdGllc1sxXSA9IDA7XG4gICAgfVxuXG4gICAgLy8gY3Jvc3MtZmFkZSBwYXJhbWV0ZXJzXG4gICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV90bF9wYXJlbnQsIHBhcmVudFRMIHx8IFswLCAwXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NjYWxlX3BhcmVudCwgcGFyZW50U2NhbGVCeSB8fCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyX3NjYWxlLCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eTAsIG9wYWNpdGllc1swXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHkxLCBvcGFjaXRpZXNbMV0pO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTAsIDApO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTEsIDEpO1xuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRpbGUuYm91bmRzQnVmZmVyIHx8IHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlcik7XG5cbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgICAgICAgICAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfdGV4dHVyZV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgOCwgNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbn1cblxuZnVuY3Rpb24gc3BpbldlaWdodHMoYW5nbGUpIHtcbiAgICBhbmdsZSAqPSBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBzID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIHZhciBjID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHJldHVybiBbXG4gICAgICAgICgyICogYyArIDEpIC8gMyxcbiAgICAgICAgKC1NYXRoLnNxcnQoMykgKiBzIC0gYyArIDEpIC8gMyxcbiAgICAgICAgKE1hdGguc3FydCgzKSAqIHMgLSBjICsgMSkgLyAzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY29udHJhc3RGYWN0b3IoY29udHJhc3QpIHtcbiAgICByZXR1cm4gY29udHJhc3QgPiAwID9cbiAgICAgICAgMSAvICgxIC0gY29udHJhc3QpIDpcbiAgICAgICAgMSArIGNvbnRyYXN0O1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0aW9uRmFjdG9yKHNhdHVyYXRpb24pIHtcbiAgICByZXR1cm4gc2F0dXJhdGlvbiA+IDAgP1xuICAgICAgICAxIC0gMSAvICgxLjAwMSAtIHNhdHVyYXRpb24pIDpcbiAgICAgICAgLXNhdHVyYXRpb247XG59XG5cbmZ1bmN0aW9uIGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgdHJhbnNmb3JtKSB7XG4gICAgaWYgKCF0aWxlLnNvdXJjZSkgcmV0dXJuIFsxLCAwXTtcblxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIHZhciBmYWRlRHVyYXRpb24gPSBsYXllci5wYWludFsncmFzdGVyLWZhZGUtZHVyYXRpb24nXTtcbiAgICB2YXIgc2luY2VUaWxlID0gKG5vdyAtIHRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbjtcbiAgICB2YXIgc2luY2VQYXJlbnQgPSBwYXJlbnRUaWxlID8gKG5vdyAtIHBhcmVudFRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbiA6IC0xO1xuXG4gICAgdmFyIGlkZWFsWiA9IHRpbGUuc291cmNlLl9weXJhbWlkLmNvdmVyaW5nWm9vbUxldmVsKHRyYW5zZm9ybSk7XG4gICAgdmFyIHBhcmVudEZ1cnRoZXIgPSBwYXJlbnRUaWxlID8gTWF0aC5hYnMocGFyZW50VGlsZS5jb29yZC56IC0gaWRlYWxaKSA+IE1hdGguYWJzKHRpbGUuY29vcmQueiAtIGlkZWFsWikgOiBmYWxzZTtcblxuICAgIHZhciBvcGFjaXR5ID0gW107XG4gICAgaWYgKCFwYXJlbnRUaWxlIHx8IHBhcmVudEZ1cnRoZXIpIHtcbiAgICAgICAgLy8gaWYgbm8gcGFyZW50IG9yIHBhcmVudCBpcyBvbGRlclxuICAgICAgICBvcGFjaXR5WzBdID0gdXRpbC5jbGFtcChzaW5jZVRpbGUsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIHlvdW5nZXIsIHpvb21pbmcgb3V0XG4gICAgICAgIG9wYWNpdHlbMF0gPSB1dGlsLmNsYW1wKDEgLSBzaW5jZVBhcmVudCwgMCwgMSk7XG4gICAgICAgIG9wYWNpdHlbMV0gPSAxIC0gb3BhY2l0eVswXTtcbiAgICB9XG5cbiAgICB2YXIgb3AgPSBsYXllci5wYWludFsncmFzdGVyLW9wYWNpdHknXTtcbiAgICBvcGFjaXR5WzBdICo9IG9wO1xuICAgIG9wYWNpdHlbMV0gKj0gb3A7XG5cbiAgICByZXR1cm4gb3BhY2l0eTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBtYXQ0ID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0NDtcblxudmFyIGRyYXdDb2xsaXNpb25EZWJ1ZyA9IHJlcXVpcmUoJy4vZHJhd19jb2xsaXNpb25fZGVidWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3U3ltYm9scztcblxuZnVuY3Rpb24gZHJhd1N5bWJvbHMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZHJhd0Fjcm9zc0VkZ2VzID0gIShsYXllci5sYXlvdXRbJ3RleHQtYWxsb3ctb3ZlcmxhcCddIHx8IGxheWVyLmxheW91dFsnaWNvbi1hbGxvdy1vdmVybGFwJ10gfHxcbiAgICAgICAgbGF5ZXIubGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXllci5sYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKTtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoZHJhd0Fjcm9zc0VkZ2VzKSB7XG4gICAgICAgIC8vIERpc2FibGUgdGhlIHN0ZW5jaWwgdGVzdCBzbyB0aGF0IGxhYmVscyBhcmVuJ3QgY2xpcHBlZCB0byB0aWxlIGJvdW5kYXJpZXMuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIExheWVycyB3aXRoIGZlYXR1cmVzIHRoYXQgbWF5IGJlIGRyYXduIG92ZXJsYXBwaW5nIGFyZW4ndCBjbGlwcGVkLiBUaGVzZVxuICAgICAgICAvLyBsYXllcnMgYXJlIHNvcnRlZCBpbiB0aGUgeSBkaXJlY3Rpb24sIGFuZCB0byBkcmF3IHRoZSBjb3JyZWN0IG9yZGVyaW5nIG5lYXJcbiAgICAgICAgLy8gdGlsZSBlZGdlcyB0aGUgaWNvbnMgYXJlIGluY2x1ZGVkIGluIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgd2hlbiBkcmF3aW5nLlxuICAgICAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRHcm91cHMudGV4dC5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2wocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSwgZWxlbWVudEdyb3Vwcy50ZXh0LCAndGV4dCcsIHRydWUpO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudEdyb3Vwcy5pY29uLmdyb3Vwcy5sZW5ndGgpIHtcbiAgICAgICAgZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLmljb24sICdpY29uJywgZWxlbWVudEdyb3Vwcy5zZGZJY29ucyk7XG4gICAgfVxuXG4gICAgZHJhd0NvbGxpc2lvbkRlYnVnKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKGRyYXdBY3Jvc3NFZGdlcykge1xuICAgICAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0U2l6ZXMgPSB7XG4gICAgaWNvbjogMSxcbiAgICB0ZXh0OiAyNFxufTtcblxuZnVuY3Rpb24gZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLCBwcmVmaXgsIHNkZikge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBwb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHRpbGUsIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlLWFuY2hvciddKTtcblxuICAgIHZhciB0ciA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgIHZhciBhbGlnbmVkV2l0aE1hcCA9IGxheWVyLmxheW91dFtwcmVmaXggKyAnLXJvdGF0aW9uLWFsaWdubWVudCddID09PSAnbWFwJztcbiAgICB2YXIgc2tld2VkID0gYWxpZ25lZFdpdGhNYXA7XG4gICAgdmFyIGV4TWF0cml4LCBzLCBnYW1tYVNjYWxlO1xuXG4gICAgaWYgKHNrZXdlZCkge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIHMgPSB0aWxlLnRpbGVFeHRlbnQgLyB0aWxlLnRpbGVTaXplIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAtIHRpbGUuY29vcmQueik7XG4gICAgICAgIGdhbW1hU2NhbGUgPSAxIC8gTWF0aC5jb3ModHIuX3BpdGNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY2xvbmUodGlsZS5leE1hdHJpeCk7XG4gICAgICAgIHMgPSBwYWludGVyLnRyYW5zZm9ybS5hbHRpdHVkZTtcbiAgICAgICAgZ2FtbWFTY2FsZSA9IDE7XG4gICAgfVxuICAgIG1hdDQuc2NhbGUoZXhNYXRyaXgsIGV4TWF0cml4LCBbcywgcywgMV0pO1xuXG4gICAgLy8gSWYgbGF5ZXIucGFpbnQuc2l6ZSA+IGxheWVyLmxheW91dFtwcmVmaXggKyAnLW1heC1zaXplJ10gdGhlbiBsYWJlbHMgbWF5IGNvbGxpZGVcbiAgICB2YXIgZm9udFNpemUgPSBsYXllci5wYWludFtwcmVmaXggKyAnLXNpemUnXTtcbiAgICB2YXIgZm9udFNjYWxlID0gZm9udFNpemUgLyBkZWZhdWx0U2l6ZXNbcHJlZml4XTtcbiAgICBtYXQ0LnNjYWxlKGV4TWF0cml4LCBleE1hdHJpeCwgWyBmb250U2NhbGUsIGZvbnRTY2FsZSwgMSBdKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBob3cgbXVjaCBsb25nZXIgdGhlIHJlYWwgd29ybGQgZGlzdGFuY2UgaXMgYXQgdGhlIHRvcCBvZiB0aGUgc2NyZWVuXG4gICAgLy8gdGhhbiBhdCB0aGUgbWlkZGxlIG9mIHRoZSBzY3JlZW4uXG4gICAgdmFyIHRvcGVkZ2VsZW5ndGggPSBNYXRoLnNxcnQodHIuaGVpZ2h0ICogdHIuaGVpZ2h0IC8gNCAgKiAoMSArIHRyLmFsdGl0dWRlICogdHIuYWx0aXR1ZGUpKTtcbiAgICB2YXIgeCA9IHRyLmhlaWdodCAvIDIgKiBNYXRoLnRhbih0ci5fcGl0Y2gpO1xuICAgIHZhciBleHRyYSA9ICh0b3BlZGdlbGVuZ3RoICsgeCkgLyB0b3BlZGdlbGVuZ3RoIC0gMTtcblxuICAgIHZhciB0ZXh0ID0gcHJlZml4ID09PSAndGV4dCc7XG4gICAgdmFyIHNoYWRlciwgdmVydGV4LCBlbGVtZW50cywgdGV4c2l6ZTtcblxuICAgIGlmICghdGV4dCAmJiAhcGFpbnRlci5zdHlsZS5zcHJpdGUubG9hZGVkKCkpXG4gICAgICAgIHJldHVybjtcblxuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgaWYgKHNkZikge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnNkZlNoYWRlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmljb25TaGFkZXI7XG4gICAgfVxuXG4gICAgaWYgKHRleHQpIHtcbiAgICAgICAgcGFpbnRlci5nbHlwaEF0bGFzLnVwZGF0ZVRleHR1cmUoZ2wpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmdseXBoRWxlbWVudDtcbiAgICAgICAgdGV4c2l6ZSA9IFtwYWludGVyLmdseXBoQXRsYXMud2lkdGggLyA0LCBwYWludGVyLmdseXBoQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcGFpbnRlci5zcHJpdGVBdGxhcy5iaW5kKGdsLCBhbGlnbmVkV2l0aE1hcCB8fCBwYWludGVyLm9wdGlvbnMucm90YXRpbmcgfHxcbiAgICAgICAgICAgIHBhaW50ZXIub3B0aW9ucy56b29taW5nIHx8IGZvbnRTY2FsZSAhPT0gMSB8fCBzZGYgfHwgcGFpbnRlci50cmFuc2Zvcm0ucGl0Y2gpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgZWxlbWVudHMgPSB0aWxlLmJ1ZmZlcnMuaWNvbkVsZW1lbnQ7XG4gICAgICAgIHRleHNpemUgPSBbcGFpbnRlci5zcHJpdGVBdGxhcy53aWR0aCAvIDQsIHBhaW50ZXIuc3ByaXRlQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfVxuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3RleHR1cmUsIDApO1xuICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfdGV4c2l6ZSwgdGV4c2l6ZSk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3NrZXdlZCwgc2tld2VkKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZXh0cmEsIGV4dHJhKTtcblxuICAgIC8vIGFkanVzdCBtaW4vbWF4IHpvb21zIGZvciB2YXJpYWJsZSBmb250IHNpZXNcbiAgICB2YXIgem9vbUFkanVzdCA9IE1hdGgubG9nKGZvbnRTaXplIC8gbGF5ZXIubGF5b3V0W3ByZWZpeCArICctbWF4LXNpemUnXSkgLyBNYXRoLkxOMiB8fCAwO1xuXG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3pvb20sIChwYWludGVyLnRyYW5zZm9ybS56b29tIC0gem9vbUFkanVzdCkgKiAxMCk7IC8vIGN1cnJlbnQgem9vbSBsZXZlbFxuXG4gICAgdmFyIGYgPSBwYWludGVyLmZyYW1lSGlzdG9yeS5nZXRGYWRlUHJvcGVydGllcygzMDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlZGlzdCwgZi5mYWRlZGlzdCAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWluZmFkZXpvb20sIE1hdGguZmxvb3IoZi5taW5mYWRlem9vbSAqIDEwKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21heGZhZGV6b29tLCBNYXRoLmZsb29yKGYubWF4ZmFkZXpvb20gKiAxMCkpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlem9vbSwgKHBhaW50ZXIudHJhbnNmb3JtLnpvb20gKyBmLmJ1bXApICogMTApO1xuXG4gICAgdmFyIGdyb3VwLCBvZmZzZXQsIGNvdW50LCBlbGVtZW50T2Zmc2V0O1xuXG4gICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICBpZiAoc2RmKSB7XG4gICAgICAgIHZhciBzZGZQeCA9IDg7XG4gICAgICAgIHZhciBibHVyT2Zmc2V0ID0gMS4xOTtcbiAgICAgICAgdmFyIGhhbG9PZmZzZXQgPSA2O1xuICAgICAgICB2YXIgZ2FtbWEgPSAwLjEwNSAqIGRlZmF1bHRTaXplc1twcmVmaXhdIC8gZm9udFNpemUgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCBnYW1tYSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBsYXllci5wYWludFtwcmVmaXggKyAnLWNvbG9yJ10pO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyLCAoMjU2IC0gNjQpIC8gMjU2KTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2ldO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pIHtcbiAgICAgICAgICAgIC8vIERyYXcgaGFsbyB1bmRlcm5lYXRoIHRoZSB0ZXh0LlxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWJsdXInXSAqIGJsdXJPZmZzZXQgLyBmb250U2NhbGUgLyBzZGZQeCArIGdhbW1hKSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgbGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKGhhbG9PZmZzZXQgLSBsYXllci5wYWludFtwcmVmaXggKyAnLWhhbG8td2lkdGgnXSAvIGZvbnRTY2FsZSkgLyBzZGZQeCk7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2pdO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgdmVydGV4LmJpbmQoZ2wsIHNoYWRlciwgb2Zmc2V0KTtcblxuICAgICAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBsYXllci5wYWludFsnaWNvbi1vcGFjaXR5J10pO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd1ZlcnRpY2VzO1xuXG5mdW5jdGlvbiBkcmF3VmVydGljZXMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoIXRpbGUgfHwgIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICBpZiAobGF5ZXIudHlwZSA9PT0gJ2ZpbGwnKSB7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXgsIGVsZW1lbnRHcm91cHMuZ3JvdXBzLCBwb3NNYXRyaXgsIDQpO1xuICAgIH0gZWxzZSBpZiAobGF5ZXIudHlwZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleCwgZWxlbWVudEdyb3Vwcy5pY29uLmdyb3VwcywgcG9zTWF0cml4LCAxNik7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmdseXBoVmVydGV4LCBlbGVtZW50R3JvdXBzLnRleHQuZ3JvdXBzLCBwb3NNYXRyaXgsIDE2KTtcbiAgICB9IGVsc2UgaWYgKGxheWVyLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgICB2YXIgbmV3UG9zTWF0cml4ID0gbWF0NC5jbG9uZShwb3NNYXRyaXgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG5ld1Bvc01hdHJpeCwgbmV3UG9zTWF0cml4LCBbMC41LCAwLjUsIDFdKTtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMubGluZVZlcnRleCwgZWxlbWVudEdyb3Vwcy5ncm91cHMsIG5ld1Bvc01hdHJpeCwgOCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1BvaW50cyh2ZXJ0ZXgsIGdyb3VwcywgbWF0cml4LCBzdHJpZGUpIHtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZG90U2hhZGVyLCBtYXRyaXgpO1xuXG4gICAgICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X3NpemUsIDQgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICBnbC51bmlmb3JtMWYocGFpbnRlci5kb3RTaGFkZXIudV9ibHVyLCAwLjI1KTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihwYWludGVyLmRvdFNoYWRlci51X2NvbG9yLCBbMC4xLCAwLCAwLCAwLjFdKTtcblxuICAgICAgICB2ZXJ0ZXguYmluZChnbCwgcGFpbnRlci5kb3RTaGFkZXIsIDApO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldO1xuICAgICAgICAgICAgdmFyIGJlZ2luID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgICAgIHZhciBjb3VudCA9IGdyb3VwLnZlcnRleExlbmd0aDtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kb3RTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCAwKTtcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCBiZWdpbiwgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gRnJhbWVIaXN0b3J5O1xuXG5mdW5jdGlvbiBGcmFtZUhpc3RvcnkoKSB7XG4gICAgdGhpcy5mcmFtZUhpc3RvcnkgPSBbXTtcbn1cblxuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5nZXRGYWRlUHJvcGVydGllcyA9IGZ1bmN0aW9uKGR1cmF0aW9uKSB7XG4gICAgaWYgKGR1cmF0aW9uID09PSB1bmRlZmluZWQpIGR1cmF0aW9uID0gMzAwO1xuICAgIHZhciBjdXJyZW50VGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBSZW1vdmUgZnJhbWVzIHVudGlsIG9ubHkgb25lIGlzIG91dHNpZGUgdGhlIGR1cmF0aW9uLCBvciB1bnRpbCB0aGVyZSBhcmUgb25seSB0aHJlZVxuICAgIHdoaWxlICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPiAzICYmIHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5LnNoaWZ0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5WzBdLnogPSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56O1xuICAgIH1cblxuICAgIHZhciBmcmFtZUxlbiA9IHRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aDtcbiAgICBpZiAoZnJhbWVMZW4gPCAzKSBjb25zb2xlLndhcm4oJ3RoZXJlIHNob3VsZCBuZXZlciBiZSBsZXNzIHRoYW4gdGhyZWUgZnJhbWVzIGluIHRoZSBoaXN0b3J5Jyk7XG5cbiAgICAvLyBGaW5kIHRoZSByYW5nZSBvZiB6b29tIGxldmVscyB3ZSB3YW50IHRvIGZhZGUgYmV0d2VlblxuICAgIHZhciBzdGFydGluZ1ogPSB0aGlzLmZyYW1lSGlzdG9yeVswXS56LFxuICAgICAgICBsYXN0RnJhbWUgPSB0aGlzLmZyYW1lSGlzdG9yeVtmcmFtZUxlbiAtIDFdLFxuICAgICAgICBlbmRpbmdaID0gbGFzdEZyYW1lLnosXG4gICAgICAgIGxvd1ogPSBNYXRoLm1pbihzdGFydGluZ1osIGVuZGluZ1opLFxuICAgICAgICBoaWdoWiA9IE1hdGgubWF4KHN0YXJ0aW5nWiwgZW5kaW5nWik7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHNwZWVkIG9mIHpvb21pbmcsIGFuZCBob3cgZmFyIGl0IHdvdWxkIHpvb20gaW4gdGVybXMgb2Ygem9vbSBsZXZlbHMgaW4gb25lIGR1cmF0aW9uXG4gICAgdmFyIHpvb21EaWZmID0gbGFzdEZyYW1lLnogLSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56LFxuICAgICAgICB0aW1lRGlmZiA9IGxhc3RGcmFtZS50aW1lIC0gdGhpcy5mcmFtZUhpc3RvcnlbMV0udGltZTtcbiAgICB2YXIgZmFkZWRpc3QgPSB6b29tRGlmZiAvICh0aW1lRGlmZiAvIGR1cmF0aW9uKTtcblxuICAgIGlmIChpc05hTihmYWRlZGlzdCkpIGNvbnNvbGUud2FybignZmFkZWRpc3Qgc2hvdWxkIG5ldmVyIGJlIE5hTicpO1xuXG4gICAgLy8gQXQgZW5kIG9mIGEgem9vbSB3aGVuIHRoZSB6b29tIHN0b3BzIGNoYW5naW5nIGNvbnRpbnVlIHByZXRlbmRpbmcgdG8gem9vbSBhdCB0aGF0IHNwZWVkXG4gICAgLy8gYnVtcCBpcyBob3cgbXVjaCBmYXJ0aGVyIGl0IHdvdWxkIGhhdmUgYmVlbiBpZiBpdCBoYWQgY29udGludWVkIHpvb21pbmcgYXQgdGhlIHNhbWUgcmF0ZVxuICAgIHZhciBidW1wID0gKGN1cnJlbnRUaW1lIC0gbGFzdEZyYW1lLnRpbWUpIC8gZHVyYXRpb24gKiBmYWRlZGlzdDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhZGVkaXN0OiBmYWRlZGlzdCxcbiAgICAgICAgbWluZmFkZXpvb206IGxvd1osXG4gICAgICAgIG1heGZhZGV6b29tOiBoaWdoWixcbiAgICAgICAgYnVtcDogYnVtcFxuICAgIH07XG59O1xuXG4vLyBSZWNvcmQgZnJhbWUgaGlzdG9yeSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYWxjdWxhdGUgZmFkaW5nIHBhcmFtc1xuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5yZWNvcmQgPSBmdW5jdGlvbih6b29tKSB7XG4gICAgdmFyIGN1cnJlbnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuICAgIC8vIGZpcnN0IGZyYW1lIGV2ZXJcbiAgICBpZiAoIXRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aCkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHt0aW1lOiAwLCB6OiB6b29tIH0sIHt0aW1lOiAwLCB6OiB6b29tIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPT09IDIgfHwgdGhpcy5mcmFtZUhpc3RvcnlbdGhpcy5mcmFtZUhpc3RvcnkubGVuZ3RoIC0gMV0ueiAhPT0gem9vbSkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHtcbiAgICAgICAgICAgIHRpbWU6IGN1cnJlbnRUaW1lLFxuICAgICAgICAgICAgejogem9vbVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxuZXhwb3J0cy5leHRlbmQgPSBmdW5jdGlvbihjb250ZXh0KSB7XG4gICAgdmFyIG9yaWdMaW5lV2lkdGggPSBjb250ZXh0LmxpbmVXaWR0aCxcbiAgICAgICAgbGluZVdpZHRoUmFuZ2UgPSBjb250ZXh0LmdldFBhcmFtZXRlcihjb250ZXh0LkFMSUFTRURfTElORV9XSURUSF9SQU5HRSk7XG5cbiAgICBjb250ZXh0LmxpbmVXaWR0aCA9IGZ1bmN0aW9uKHdpZHRoKSB7XG4gICAgICAgIG9yaWdMaW5lV2lkdGguY2FsbChjb250ZXh0LCB1dGlsLmNsYW1wKHdpZHRoLCBsaW5lV2lkdGhSYW5nZVswXSwgbGluZVdpZHRoUmFuZ2VbMV0pKTtcbiAgICB9O1xuXG4gICAgY29udGV4dC5nZXRTaGFkZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlKSB7XG4gICAgICAgIHZhciBraW5kID0gdHlwZSA9PT0gdGhpcy5GUkFHTUVOVF9TSEFERVIgPyAnZnJhZ21lbnQnIDogJ3ZlcnRleCc7XG4gICAgICAgIGlmICghc2hhZGVyc1tuYW1lXSB8fCAhc2hhZGVyc1tuYW1lXVtraW5kXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgc2hhZGVyIFwiICsgbmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hhZGVyID0gdGhpcy5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgIHRoaXMuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyc1tuYW1lXVtraW5kXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICBpZiAoIXRoaXMuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgdGhpcy5DT01QSUxFX1NUQVRVUykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNoYWRlcjtcbiAgICB9O1xuXG4gICAgY29udGV4dC5pbml0aWFsaXplU2hhZGVyID0gZnVuY3Rpb24obmFtZSwgYXR0cmlidXRlcywgdW5pZm9ybXMpIHtcbiAgICAgICAgdmFyIHNoYWRlciA9IHtcbiAgICAgICAgICAgIHByb2dyYW06IHRoaXMuY3JlYXRlUHJvZ3JhbSgpLFxuICAgICAgICAgICAgZnJhZ21lbnQ6IHRoaXMuZ2V0U2hhZGVyKG5hbWUsIHRoaXMuRlJBR01FTlRfU0hBREVSKSxcbiAgICAgICAgICAgIHZlcnRleDogdGhpcy5nZXRTaGFkZXIobmFtZSwgdGhpcy5WRVJURVhfU0hBREVSKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYXR0YWNoU2hhZGVyKHNoYWRlci5wcm9ncmFtLCBzaGFkZXIudmVydGV4KTtcbiAgICAgICAgdGhpcy5hdHRhY2hTaGFkZXIoc2hhZGVyLnByb2dyYW0sIHNoYWRlci5mcmFnbWVudCk7XG4gICAgICAgIHRoaXMubGlua1Byb2dyYW0oc2hhZGVyLnByb2dyYW0pO1xuXG4gICAgICAgIGlmICghdGhpcy5nZXRQcm9ncmFtUGFyYW1ldGVyKHNoYWRlci5wcm9ncmFtLCB0aGlzLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLmdldFByb2dyYW1JbmZvTG9nKHNoYWRlci5wcm9ncmFtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJbYXR0cmlidXRlc1tpXV0gPSB0aGlzLmdldEF0dHJpYkxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCBhdHRyaWJ1dGVzW2ldKTtcbiAgICAgICAgICAgICAgICBzaGFkZXIuYXR0cmlidXRlcy5wdXNoKHNoYWRlclthdHRyaWJ1dGVzW2ldXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHVuaWZvcm1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgc2hhZGVyW3VuaWZvcm1zW2tdXSA9IHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCB1bmlmb3Jtc1trXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH07XG5cbiAgICAvLyBTd2l0Y2hlcyB0byBhIGRpZmZlcmVudCBzaGFkZXIgcHJvZ3JhbS5cbiAgICBjb250ZXh0LnN3aXRjaFNoYWRlciA9IGZ1bmN0aW9uKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCkge1xuICAgICAgICBpZiAoIXBvc01hdHJpeCkge1xuICAgICAgICAgICAgY29uc29sZS50cmFjZSgncG9zTWF0cml4IGRvZXMgbm90IGhhdmUgcmVxdWlyZWQgYXJndW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTaGFkZXIgIT09IHNoYWRlcikge1xuICAgICAgICAgICAgdGhpcy51c2VQcm9ncmFtKHNoYWRlci5wcm9ncmFtKTtcblxuICAgICAgICAgICAgLy8gRGlzYWJsZSBhbGwgYXR0cmlidXRlcyBmcm9tIHRoZSBleGlzdGluZyBzaGFkZXIgdGhhdCBhcmVuJ3QgdXNlZCBpblxuICAgICAgICAgICAgLy8gdGhlIG5ldyBzaGFkZXIuIE5vdGU6IGF0dHJpYnV0ZSBpbmRpY2VzIGFyZSAqbm90KiBwcm9ncmFtIHNwZWNpZmljIVxuICAgICAgICAgICAgdmFyIGVuYWJsZWQgPSB0aGlzLmN1cnJlbnRTaGFkZXIgPyB0aGlzLmN1cnJlbnRTaGFkZXIuYXR0cmlidXRlcyA6IFtdO1xuICAgICAgICAgICAgdmFyIHJlcXVpcmVkID0gc2hhZGVyLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW5hYmxlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlZC5pbmRleE9mKGVuYWJsZWRbaV0pIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShlbmFibGVkW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVuYWJsZSBhbGwgYXR0cmlidXRlcyBmb3IgdGhlIG5ldyBzaGFkZXIuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlcXVpcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVuYWJsZWQuaW5kZXhPZihyZXF1aXJlZFtqXSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkocmVxdWlyZWRbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U2hhZGVyID0gc2hhZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtYXRyaWNlcyBpZiBuZWNlc3NhcnkuIE5vdGU6IFRoaXMgcmVsaWVzIG9uIG9iamVjdCBpZGVudGl0eSFcbiAgICAgICAgLy8gVGhpcyBtZWFucyBjaGFuZ2luZyB0aGUgbWF0cml4IHZhbHVlcyB3aXRob3V0IHRoZSBhY3R1YWwgbWF0cml4IG9iamVjdFxuICAgICAgICAvLyB3aWxsIEZBSUwgdG8gdXBkYXRlIHRoZSBtYXRyaXggcHJvcGVybHkuXG4gICAgICAgIGlmIChzaGFkZXIucG9zTWF0cml4ICE9PSBwb3NNYXRyaXgpIHtcbiAgICAgICAgICAgIHRoaXMudW5pZm9ybU1hdHJpeDRmdihzaGFkZXIudV9tYXRyaXgsIGZhbHNlLCBwb3NNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLnBvc01hdHJpeCA9IHBvc01hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhNYXRyaXggJiYgc2hhZGVyLmV4TWF0cml4ICE9PSBleE1hdHJpeCAmJiBzaGFkZXIudV9leG1hdHJpeCkge1xuICAgICAgICAgICAgdGhpcy51bmlmb3JtTWF0cml4NGZ2KHNoYWRlci51X2V4bWF0cml4LCBmYWxzZSwgZXhNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLmV4TWF0cml4ID0gZXhNYXRyaXg7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVBdGxhcztcblxuLyoqXG4gKiBNdWNoIGxpa2UgYSBHbHlwaEF0bGFzLCBhIExpbmVBdGxhcyBsZXRzIHVzIHJldXNlIHJlbmRlcmVkIGRhc2hlZCBsaW5lc1xuICogYnkgd3JpdGluZyBtYW55IG9mIHRoZW0gdG8gYSB0ZXh0dXJlIGFuZCB0aGVuIGZldGNoaW5nIHRoZWlyIHBvc2l0aW9uc1xuICogdXNpbmcgLmdldERhc2guXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBMaW5lQXRsYXMod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLm5leHRSb3cgPSAwO1xuXG4gICAgdGhpcy5ieXRlcyA9IDQ7XG4gICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy53aWR0aCAqIHRoaXMuaGVpZ2h0ICogdGhpcy5ieXRlcyk7XG5cbiAgICB0aGlzLnBvc2l0aW9ucyA9IHt9O1xufVxuXG5MaW5lQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuLyoqXG4gKiBHZXQgb3IgY3JlYXRlIGEgZGFzaCBsaW5lIHBhdHRlcm4uXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBkYXNoYXJyYXlcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gcm91bmQgd2hldGhlciB0byBhZGQgY2lyY2xlIGNhcHMgaW4gYmV0d2VlbiBkYXNoIHNlZ21lbnRzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwb3NpdGlvbiBvZiBkYXNoIHRleHR1cmUgaW4geyB5LCBoZWlnaHQsIHdpZHRoIH1cbiAqIEBwcml2YXRlXG4gKi9cbkxpbmVBdGxhcy5wcm90b3R5cGUuZ2V0RGFzaCA9IGZ1bmN0aW9uKGRhc2hhcnJheSwgcm91bmQpIHtcbiAgICB2YXIga2V5ID0gZGFzaGFycmF5LmpvaW4oXCIsXCIpICsgcm91bmQ7XG5cbiAgICBpZiAoIXRoaXMucG9zaXRpb25zW2tleV0pIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbnNba2V5XSA9IHRoaXMuYWRkRGFzaChkYXNoYXJyYXksIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucG9zaXRpb25zW2tleV07XG59O1xuXG5MaW5lQXRsYXMucHJvdG90eXBlLmFkZERhc2ggPSBmdW5jdGlvbihkYXNoYXJyYXksIHJvdW5kKSB7XG5cbiAgICB2YXIgbiA9IHJvdW5kID8gNyA6IDA7XG4gICAgdmFyIGhlaWdodCA9IDIgKiBuICsgMTtcbiAgICB2YXIgb2Zmc2V0ID0gMTI4O1xuXG4gICAgaWYgKHRoaXMubmV4dFJvdyArIGhlaWdodCA+IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTGluZUF0bGFzIG91dCBvZiBzcGFjZScpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhc2hhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZW5ndGggKz0gZGFzaGFycmF5W2ldO1xuICAgIH1cblxuICAgIHZhciBzdHJldGNoID0gdGhpcy53aWR0aCAvIGxlbmd0aDtcbiAgICB2YXIgaGFsZldpZHRoID0gc3RyZXRjaCAvIDI7XG5cbiAgICAvLyBJZiBkYXNoYXJyYXkgaGFzIGFuIG9kZCBsZW5ndGgsIGJvdGggdGhlIGZpcnN0IGFuZCBsYXN0IHBhcnRzXG4gICAgLy8gYXJlIGRhc2hlcyBhbmQgc2hvdWxkIGJlIGpvaW5lZCBzZWFtbGVzc2x5LlxuICAgIHZhciBvZGRMZW5ndGggPSBkYXNoYXJyYXkubGVuZ3RoICUgMiA9PT0gMTtcblxuICAgIGZvciAodmFyIHkgPSAtbjsgeSA8PSBuOyB5KyspIHtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMubmV4dFJvdyArIG4gKyB5O1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLndpZHRoICogcm93O1xuXG4gICAgICAgIHZhciBsZWZ0ID0gb2RkTGVuZ3RoID8gLWRhc2hhcnJheVtkYXNoYXJyYXkubGVuZ3RoIC0gMV0gOiAwO1xuICAgICAgICB2YXIgcmlnaHQgPSBkYXNoYXJyYXlbMF07XG4gICAgICAgIHZhciBwYXJ0SW5kZXggPSAxO1xuXG4gICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgdGhpcy53aWR0aDsgeCsrKSB7XG5cbiAgICAgICAgICAgIHdoaWxlIChyaWdodCA8IHggLyBzdHJldGNoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQgKyBkYXNoYXJyYXlbcGFydEluZGV4XTtcblxuICAgICAgICAgICAgICAgIGlmIChvZGRMZW5ndGggJiYgcGFydEluZGV4ID09PSBkYXNoYXJyYXkubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICByaWdodCArPSBkYXNoYXJyYXlbMF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcGFydEluZGV4Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBkaXN0TGVmdCA9IE1hdGguYWJzKHggLSBsZWZ0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdFJpZ2h0ID0gTWF0aC5hYnMoeCAtIHJpZ2h0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdCA9IE1hdGgubWluKGRpc3RMZWZ0LCBkaXN0UmlnaHQpO1xuICAgICAgICAgICAgdmFyIGluc2lkZSA9IChwYXJ0SW5kZXggJSAyKSA9PT0gMTtcbiAgICAgICAgICAgIHZhciBzaWduZWREaXN0YW5jZTtcblxuICAgICAgICAgICAgaWYgKHJvdW5kKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGNpcmNsZSBjYXBzXG4gICAgICAgICAgICAgICAgdmFyIGRpc3RNaWRkbGUgPSBuID8geSAvIG4gKiAoaGFsZldpZHRoICsgMSkgOiAwO1xuICAgICAgICAgICAgICAgIGlmIChpbnNpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RFZGdlID0gaGFsZldpZHRoIC0gTWF0aC5hYnMoZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgICAgIHNpZ25lZERpc3RhbmNlID0gTWF0aC5zcXJ0KGRpc3QgKiBkaXN0ICsgZGlzdEVkZ2UgKiBkaXN0RWRnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2lnbmVkRGlzdGFuY2UgPSBoYWxmV2lkdGggLSBNYXRoLnNxcnQoZGlzdCAqIGRpc3QgKyBkaXN0TWlkZGxlICogZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduZWREaXN0YW5jZSA9IChpbnNpZGUgPyAxIDogLTEpICogZGlzdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5kYXRhWzMgKyAoaW5kZXggKyB4KSAqIDRdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBzaWduZWREaXN0YW5jZSArIG9mZnNldCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHtcbiAgICAgICAgeTogKHRoaXMubmV4dFJvdyArIG4gKyAwLjUpIC8gdGhpcy5oZWlnaHQsXG4gICAgICAgIGhlaWdodDogMiAqIG4gLyB0aGlzLmhlaWdodCxcbiAgICAgICAgd2lkdGg6IGxlbmd0aFxuICAgIH07XG5cbiAgICB0aGlzLm5leHRSb3cgKz0gaGVpZ2h0O1xuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHBvcztcbn07XG5cbkxpbmVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHRoaXMuZGF0YSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuXG4gICAgICAgIGlmICh0aGlzLmRpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLmRhdGEpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuTGluZUF0bGFzLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIGNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgY2FudmFzLnN0eWxlLnRvcCA9IDA7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAwO1xuICAgIGNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kID0gJyNmZjAnO1xuXG4gICAgY2FudmFzLndpZHRoID0gdGhpcy53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdmFyIGRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5zZGYpIHtcbiAgICAgICAgICAgIHZhciBrID0gaSAqIDQ7XG4gICAgICAgICAgICBkYXRhLmRhdGFba10gPSBkYXRhLmRhdGFbayArIDFdID0gZGF0YS5kYXRhW2sgKyAyXSA9IDA7XG4gICAgICAgICAgICBkYXRhLmRhdGFbayArIDNdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0YS5kYXRhW2ldID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5wdXRJbWFnZURhdGEoZGF0YSwgMCwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2x1dGlsID0gcmVxdWlyZSgnLi9nbF91dGlsJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDQgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQ0O1xudmFyIEZyYW1lSGlzdG9yeSA9IHJlcXVpcmUoJy4vZnJhbWVfaGlzdG9yeScpO1xuXG4vKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBwYWludGVyIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0NhbnZhc30gZ2wgYW4gZXhwZXJpbWVudGFsLXdlYmdsIGRyYXdpbmcgY29udGV4dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IFBhaW50ZXI7XG5mdW5jdGlvbiBQYWludGVyKGdsLCB0cmFuc2Zvcm0pIHtcbiAgICB0aGlzLmdsID0gZ2x1dGlsLmV4dGVuZChnbCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5cbiAgICB0aGlzLnJldXNhYmxlVGV4dHVyZXMgPSB7fTtcbiAgICB0aGlzLnByZUZib3MgPSB7fTtcblxuICAgIHRoaXMuZnJhbWVIaXN0b3J5ID0gbmV3IEZyYW1lSGlzdG9yeSgpO1xuXG4gICAgdGhpcy5zZXR1cCgpO1xufVxuXG4vKlxuICogVXBkYXRlIHRoZSBHTCB2aWV3cG9ydCwgcHJvamVjdGlvbiBtYXRyaXgsIGFuZCB0cmFuc2Zvcm1zIHRvIGNvbXBlbnNhdGVcbiAqIGZvciBhIG5ldyB3aWR0aCBhbmQgaGVpZ2h0IHZhbHVlLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcblxuICAgIHRoaXMud2lkdGggPSB3aWR0aCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICBnbC52aWV3cG9ydCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cbn07XG5cblxuUGFpbnRlci5wcm90b3R5cGUuc2V0dXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgZ2wudmVyYm9zZSA9IHRydWU7XG5cbiAgICAvLyBXZSBhcmUgYmxlbmRpbmcgdGhlIG5ldyBwaXhlbHMgKmJlaGluZCogdGhlIGV4aXN0aW5nIHBpeGVscy4gVGhhdCB3YXkgd2UgY2FuXG4gICAgLy8gZHJhdyBmcm9udC10by1iYWNrIGFuZCB1c2UgdGhlbiBzdGVuY2lsIGJ1ZmZlciB0byBjdWxsIG9wYXF1ZSBwaXhlbHMgZWFybHkuXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKTtcbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FX01JTlVTX0RTVF9BTFBIQSwgZ2wuT05FKTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFkZXJzXG4gICAgdGhpcy5kZWJ1Z1NoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2RlYnVnJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfcG9pbnRzaXplJywgJ3VfY29sb3InXSk7XG5cbiAgICB0aGlzLmdhdXNzaWFuU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZ2F1c3NpYW4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9pbWFnZScsICd1X29mZnNldCddKTtcblxuICAgIHRoaXMucmFzdGVyU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcigncmFzdGVyJyxcbiAgICAgICAgWydhX3BvcycsICdhX3RleHR1cmVfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9icmlnaHRuZXNzX2xvdycsICd1X2JyaWdodG5lc3NfaGlnaCcsICd1X3NhdHVyYXRpb25fZmFjdG9yJywgJ3Vfc3Bpbl93ZWlnaHRzJywgJ3VfY29udHJhc3RfZmFjdG9yJywgJ3Vfb3BhY2l0eTAnLCAndV9vcGFjaXR5MScsICd1X2ltYWdlMCcsICd1X2ltYWdlMScsICd1X3RsX3BhcmVudCcsICd1X3NjYWxlX3BhcmVudCcsICd1X2J1ZmZlcl9zY2FsZSddKTtcblxuICAgIHRoaXMubGluZVNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2xpbmUnLFxuICAgICAgICBbJ2FfcG9zJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfbGluZXdpZHRoJywgJ3VfY29sb3InLCAndV9yYXRpbycsICd1X2JsdXInLCAndV9leHRyYScsICd1X2FudGlhbGlhc2luZ21hdHJpeCddKTtcblxuICAgIHRoaXMubGluZXBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X3JhdGlvJywgJ3VfcGF0dGVybl9zaXplX2EnLCAndV9wYXR0ZXJuX3NpemVfYicsICd1X3BhdHRlcm5fdGxfYScsICd1X3BhdHRlcm5fYnJfYScsICd1X3BhdHRlcm5fdGxfYicsICd1X3BhdHRlcm5fYnJfYicsICd1X2JsdXInLCAndV9mYWRlJywgJ3Vfb3BhY2l0eSddKTtcblxuICAgIHRoaXMubGluZXNkZnBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lc2RmcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X2NvbG9yJywgJ3VfcmF0aW8nLCAndV9ibHVyJywgJ3VfcGF0dGVybnNjYWxlX2EnLCAndV90ZXhfeV9hJywgJ3VfcGF0dGVybnNjYWxlX2InLCAndV90ZXhfeV9iJywgJ3VfaW1hZ2UnLCAndV9zZGZnYW1tYScsICd1X21peCddKTtcblxuICAgIHRoaXMuZG90U2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZG90JyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2l6ZScsICd1X2NvbG9yJywgJ3VfYmx1ciddKTtcblxuICAgIHRoaXMuc2RmU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignc2RmJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV9jb2xvcicsICd1X2dhbW1hJywgJ3VfYnVmZmVyJywgJ3Vfem9vbScsICd1X2ZhZGVkaXN0JywgJ3VfbWluZmFkZXpvb20nLCAndV9tYXhmYWRlem9vbScsICd1X2ZhZGV6b29tJywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLmljb25TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdpY29uJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV96b29tJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nLCAndV9vcGFjaXR5JywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLm91dGxpbmVTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdvdXRsaW5lJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InLCAndV93b3JsZCddXG4gICAgKTtcblxuICAgIHRoaXMucGF0dGVyblNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ3BhdHRlcm4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9wYXR0ZXJuX3RsX2EnLCAndV9wYXR0ZXJuX2JyX2EnLCAndV9wYXR0ZXJuX3RsX2InLCAndV9wYXR0ZXJuX2JyX2InLCAndV9taXgnLCAndV9wYXR0ZXJubWF0cml4X2EnLCAndV9wYXR0ZXJubWF0cml4X2InLCAndV9vcGFjaXR5JywgJ3VfaW1hZ2UnXVxuICAgICk7XG5cbiAgICB0aGlzLmZpbGxTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdmaWxsJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InXVxuICAgICk7XG5cbiAgICB0aGlzLmNvbGxpc2lvbkJveFNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2NvbGxpc2lvbmJveCcsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9leHRydWRlJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2NhbGUnLCAndV96b29tJywgJ3VfbWF4em9vbSddXG4gICAgKTtcblxuICAgIHRoaXMuaWRlbnRpdHlNYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuXG4gICAgLy8gVGhlIGJhY2tncm91bmRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gdGhlIGZ1bGwgKmNhbnZhcypcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUgPSAyO1xuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQgPSA0O1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCBuZXcgSW50MTZBcnJheShbLTEsIC0xLCAxLCAtMSwgLTEsIDEsIDEsIDFdKSwgZ2wuU1RBVElDX0RSQVcpO1xuXG4gICAgdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG5cbiAgICAvLyBUaGUgZGVidWdUZXh0QnVmZmVyIGlzIHVzZWQgdG8gZHJhdyB0aWxlIElEcyBmb3IgZGVidWdnaW5nXG4gICAgdGhpcy5kZWJ1Z1RleHRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnVGV4dEJ1ZmZlci5pdGVtU2l6ZSA9IDI7XG59O1xuXG4vKipcbiAqIFJlYmluZCB0aGUgbmVjZXNzYXJ5IGJ1ZmZlcnMgdG8gcmVuZGVyIGF0IGEgZGlmZmVyZW50IGV4dGVudCB0aGFuXG4gKiB0aGUgY3VycmVudCBvbmUuIE5vLW9wcyBpZiB0aGUgZXh0ZW50IGlzIG5vdCBjaGFuZ2luZy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbmV3RXh0ZW50XG4gKiBAZXhhbXBsZVxuICogdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG4gKi9cblBhaW50ZXIucHJvdG90eXBlLnNldEV4dGVudCA9IGZ1bmN0aW9uKG5ld0V4dGVudCkge1xuICAgIGlmICghbmV3RXh0ZW50IHx8IG5ld0V4dGVudCA9PT0gdGhpcy50aWxlRXh0ZW50KSByZXR1cm47XG5cbiAgICB0aGlzLnRpbGVFeHRlbnQgPSBuZXdFeHRlbnQ7XG5cbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgLy8gVGhlIHRpbGVFeHRlbnRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gYSBmdWxsICp0aWxlKlxuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlci5pdGVtU2l6ZSA9IDQ7XG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCA9IDQ7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudGlsZUV4dGVudEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShcbiAgICAgICAgZ2wuQVJSQVlfQlVGRkVSLFxuICAgICAgICBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICAvLyB0aWxlIGNvb3JkIHgsIHRpbGUgY29vcmQgeSwgdGV4dHVyZSBjb29yZCB4LCB0ZXh0dXJlIGNvb3JkIHlcbiAgICAgICAgICAgIDAsIDAsIDAsIDAsXG4gICAgICAgICAgICB0aGlzLnRpbGVFeHRlbnQsIDAsIDMyNzY3LCAwLFxuICAgICAgICAgICAgMCwgdGhpcy50aWxlRXh0ZW50LCAwLCAzMjc2NyxcbiAgICAgICAgICAgIHRoaXMudGlsZUV4dGVudCwgdGhpcy50aWxlRXh0ZW50LCAgMzI3NjcsIDMyNzY3XG4gICAgICAgIF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAvLyBUaGUgZGVidWdCdWZmZXIgaXMgdXNlZCB0byBkcmF3IHRpbGUgb3V0bGluZXMgZm9yIGRlYnVnZ2luZ1xuICAgIHRoaXMuZGVidWdCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1TaXplID0gMjtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1Db3VudCA9IDU7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuZGVidWdCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoXG4gICAgICAgIGdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgbmV3IEludDE2QXJyYXkoW1xuICAgICAgICAgICAgMCwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgMF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG59O1xuXG4vKlxuICogUmVzZXQgdGhlIGNvbG9yIGJ1ZmZlcnMgb2YgdGhlIGRyYXdpbmcgY2FudmFzLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5jbGVhckNvbG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5jbGVhckNvbG9yKDAsIDAsIDAsIDApO1xuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xufTtcblxuLypcbiAqIFJlc2V0IHRoZSBkcmF3aW5nIGNhbnZhcyBieSBjbGVhcmluZyB0aGUgc3RlbmNpbCBidWZmZXIgc28gdGhhdCB3ZSBjYW4gZHJhd1xuICogbmV3IHRpbGVzIGF0IHRoZSBzYW1lIGxvY2F0aW9uLCB3aGlsZSByZXRhaW5pbmcgcHJldmlvdXNseSBkcmF3biBwaXhlbHMuXG4gKi9cblBhaW50ZXIucHJvdG90eXBlLmNsZWFyU3RlbmNpbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhGRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdDbGlwcGluZ01hc2sgPSBmdW5jdGlvbih0aWxlKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5zd2l0Y2hTaGFkZXIodGhpcy5maWxsU2hhZGVyLCB0aWxlLnBvc01hdHJpeCk7XG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIENsZWFyIHRoZSBlbnRpcmUgc3RlbmNpbCBidWZmZXIsIGV4Y2VwdCBmb3IgdGhlIDd0aCBiaXQsIHdoaWNoIHN0b3Jlc1xuICAgIC8vIHRoZSBnbG9iYWwgY2xpcHBpbmcgbWFzayB0aGF0IGFsbG93cyB1cyB0byBhdm9pZCBkcmF3aW5nIGluIHJlZ2lvbnMgb2ZcbiAgICAvLyB0aWxlcyB3ZSd2ZSBhbHJlYWR5IHBhaW50ZWQgaW4uXG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhCRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIFRoZSBzdGVuY2lsIHRlc3Qgd2lsbCBmYWlsIGFsd2F5cywgbWVhbmluZyB3ZSBzZXQgYWxsIHBpeGVscyBjb3ZlcmVkXG4gICAgLy8gYnkgdGhpcyBnZW9tZXRyeSB0byAweDgwLiBXZSB1c2UgdGhlIGhpZ2hlc3QgYml0IDB4ODAgdG8gbWFyayB0aGUgcmVnaW9uc1xuICAgIC8vIHdlIHdhbnQgdG8gZHJhdyBpbi4gQWxsIHBpeGVscyB0aGF0IGhhdmUgdGhpcyBiaXQgKm5vdCogc2V0IHdpbGwgbmV2ZXIgYmVcbiAgICAvLyBkcmF3biBpbi5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHhDMCwgMHg0MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhDMCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLlJFUExBQ0UsIGdsLktFRVAsIGdsLktFRVApO1xuXG4gICAgLy8gRHJhdyB0aGUgY2xpcHBpbmcgbWFza1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgOCwgMCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLktFRVAsIGdsLktFRVAsIGdsLlJFUExBQ0UpO1xuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcbn07XG5cbi8vIE92ZXJyaWRkZW4gYnkgaGVhZGxlc3MgdGVzdHMuXG5QYWludGVyLnByb3RvdHlwZS5wcmVwYXJlQnVmZmVycyA9IGZ1bmN0aW9uKCkge307XG5QYWludGVyLnByb3RvdHlwZS5iaW5kRGVmYXVsdEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xufTtcblxudmFyIGRyYXcgPSB7XG4gICAgc3ltYm9sOiByZXF1aXJlKCcuL2RyYXdfc3ltYm9sJyksXG4gICAgbGluZTogcmVxdWlyZSgnLi9kcmF3X2xpbmUnKSxcbiAgICBmaWxsOiByZXF1aXJlKCcuL2RyYXdfZmlsbCcpLFxuICAgIHJhc3RlcjogcmVxdWlyZSgnLi9kcmF3X3Jhc3RlcicpLFxuICAgIGJhY2tncm91bmQ6IHJlcXVpcmUoJy4vZHJhd19iYWNrZ3JvdW5kJyksXG4gICAgZGVidWc6IHJlcXVpcmUoJy4vZHJhd19kZWJ1ZycpLFxuICAgIHZlcnRpY2VzOiByZXF1aXJlKCcuL2RyYXdfdmVydGljZXMnKVxufTtcblxuUGFpbnRlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24oc3R5bGUsIG9wdGlvbnMpIHtcbiAgICB0aGlzLnN0eWxlID0gc3R5bGU7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIHRoaXMubGluZUF0bGFzID0gc3R5bGUubGluZUF0bGFzO1xuXG4gICAgdGhpcy5zcHJpdGVBdGxhcyA9IHN0eWxlLnNwcml0ZUF0bGFzO1xuICAgIHRoaXMuc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHN0eWxlLnNwcml0ZSk7XG5cbiAgICB0aGlzLmdseXBoQXRsYXMgPSBzdHlsZS5nbHlwaEF0bGFzO1xuICAgIHRoaXMuZ2x5cGhBdGxhcy5iaW5kKHRoaXMuZ2wpO1xuXG4gICAgdGhpcy5mcmFtZUhpc3RvcnkucmVjb3JkKHRoaXMudHJhbnNmb3JtLnpvb20pO1xuXG4gICAgdGhpcy5wcmVwYXJlQnVmZmVycygpO1xuICAgIHRoaXMuY2xlYXJDb2xvcigpO1xuXG4gICAgZm9yICh2YXIgaSA9IHN0eWxlLl9ncm91cHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGdyb3VwID0gc3R5bGUuX2dyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHN0eWxlLnNvdXJjZXNbZ3JvdXAuc291cmNlXTtcblxuICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyU3RlbmNpbCgpO1xuICAgICAgICAgICAgc291cmNlLnJlbmRlcihncm91cCwgdGhpcyk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChncm91cC5zb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3TGF5ZXJzKGdyb3VwLCB0aGlzLmlkZW50aXR5TWF0cml4KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdUaWxlID0gZnVuY3Rpb24odGlsZSwgbGF5ZXJzKSB7XG4gICAgdGhpcy5zZXRFeHRlbnQodGlsZS50aWxlRXh0ZW50KTtcbiAgICB0aGlzLmRyYXdDbGlwcGluZ01hc2sodGlsZSk7XG4gICAgdGhpcy5kcmF3TGF5ZXJzKGxheWVycywgdGlsZS5wb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kZWJ1Zykge1xuICAgICAgICBkcmF3LmRlYnVnKHRoaXMsIHRpbGUpO1xuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdMYXllcnMgPSBmdW5jdGlvbihsYXllcnMsIG1hdHJpeCwgdGlsZSkge1xuICAgIGZvciAodmFyIGkgPSBsYXllcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5oaWRkZW4pXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBkcmF3W2xheWVyLnR5cGVdKHRoaXMsIGxheWVyLCBtYXRyaXgsIHRpbGUpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmVydGljZXMpIHtcbiAgICAgICAgICAgIGRyYXcudmVydGljZXModGhpcywgbGF5ZXIsIG1hdHJpeCwgdGlsZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBEcmF3cyBub24tb3BhcXVlIGFyZWFzLiBUaGlzIGlzIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG5QYWludGVyLnByb3RvdHlwZS5kcmF3U3RlbmNpbEJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHRoaXMuZmlsbFNoYWRlciwgdGhpcy5pZGVudGl0eU1hdHJpeCk7XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweDAwKTtcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG5cbiAgICAvLyBEcncgdGhlIGZpbGxpbmcgcXVhZCB3aGVyZSB0aGUgc3RlbmNpbCBidWZmZXIgaXNuJ3Qgc2V0LlxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wudW5pZm9ybTRmdih0aGlzLmZpbGxTaGFkZXIudV9jb2xvciwgWzAsIDAsIDAsIDAuNV0pO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59O1xuXG5QYWludGVyLnByb3RvdHlwZS50cmFuc2xhdGVNYXRyaXggPSBmdW5jdGlvbihtYXRyaXgsIHRpbGUsIHRyYW5zbGF0ZSwgYW5jaG9yKSB7XG4gICAgaWYgKCF0cmFuc2xhdGVbMF0gJiYgIXRyYW5zbGF0ZVsxXSkgcmV0dXJuIG1hdHJpeDtcblxuICAgIGlmIChhbmNob3IgPT09ICd2aWV3cG9ydCcpIHtcbiAgICAgICAgdmFyIHNpbkEgPSBNYXRoLnNpbigtdGhpcy50cmFuc2Zvcm0uYW5nbGUpO1xuICAgICAgICB2YXIgY29zQSA9IE1hdGguY29zKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHRyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVswXSAqIGNvc0EgLSB0cmFuc2xhdGVbMV0gKiBzaW5BLFxuICAgICAgICAgICAgdHJhbnNsYXRlWzBdICogc2luQSArIHRyYW5zbGF0ZVsxXSAqIGNvc0FcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICB2YXIgdGlsZVBpeGVsUmF0aW8gPSB0aGlzLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHRyYW5zbGF0aW9uID0gW1xuICAgICAgICB0cmFuc2xhdGVbMF0gLyB0aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdHJhbnNsYXRlWzFdIC8gdGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIDBcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBtYXQ0LnRyYW5zbGF0ZSh0cmFuc2xhdGVkTWF0cml4LCBtYXRyaXgsIHRyYW5zbGF0aW9uKTtcbiAgICByZXR1cm4gdHJhbnNsYXRlZE1hdHJpeDtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLnNhdmVUZXh0dXJlID0gZnVuY3Rpb24odGV4dHVyZSkge1xuICAgIHZhciB0ZXh0dXJlcyA9IHRoaXMucmV1c2FibGVUZXh0dXJlc1t0ZXh0dXJlLnNpemVdO1xuICAgIGlmICghdGV4dHVyZXMpIHtcbiAgICAgICAgdGhpcy5yZXVzYWJsZVRleHR1cmVzW3RleHR1cmUuc2l6ZV0gPSBbdGV4dHVyZV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHVyZXMucHVzaCh0ZXh0dXJlKTtcbiAgICB9XG59O1xuXG5cblBhaW50ZXIucHJvdG90eXBlLmdldFRleHR1cmUgPSBmdW5jdGlvbihzaXplKSB7XG4gICAgdmFyIHRleHR1cmVzID0gdGhpcy5yZXVzYWJsZVRleHR1cmVzW3NpemVdO1xuICAgIHJldHVybiB0ZXh0dXJlcyAmJiB0ZXh0dXJlcy5sZW5ndGggPiAwID8gdGV4dHVyZXMucG9wKCkgOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGdsaWZ5ID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBcImRlYnVnXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBmbG9hdCB1X3BvaW50c2l6ZTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcyxzdGVwKDMyNzY3LixhX3Bvcy54KSwxKTtnbF9Qb2ludFNpemU9dV9wb2ludHNpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZvaWQgbWFpbigpe2dsX0ZyYWdDb2xvcj11X2NvbG9yO31cIn0sXG4gICAgXCJkb3RcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBmbG9hdCB1X3NpemU7YXR0cmlidXRlIHZlYzIgYV9wb3M7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT11X3NpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3VuaWZvcm0gZmxvYXQgdV9ibHVyO3ZvaWQgbWFpbigpe2Zsb2F0IGEsYjthPWxlbmd0aChnbF9Qb2ludENvb3JkLS41KTtiPXNtb290aHN0ZXAoLjUsLjUtdV9ibHVyLGEpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmI7fVwifSxcbiAgICBcImZpbGxcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT0yLjt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXVfY29sb3I7fVwifSxcbiAgICBcImdhdXNzaWFuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X29mZnNldDt2YXJ5aW5nIHZlYzIgYVszXTt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dmVjMiBiPWdsX1Bvc2l0aW9uLnh5LzIuKy41O2FbMF09YjthWzFdPWIrdV9vZmZzZXQqMS4xODI0MjU1MjM4MDYzNTYzO2FbMl09Yi11X29mZnNldCoxLjE4MjQyNTUyMzgwNjM1NjM7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGFbM107dm9pZCBtYWluKCl7dmVjNCBiPXZlYzQoMCk7Yis9dGV4dHVyZTJEKHVfaW1hZ2UsYVswXSkqLjQwMjYxOTk0Njg5NDI0NzQ2O2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMV0pKi4yOTg2OTAwMjY1NTI4NzYzO2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMl0pKi4yOTg2OTAwMjY1NTI4NzYzO2dsX0ZyYWdDb2xvcj1iO31cIn0sXG4gICAgXCJsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW8sdV9leHRyYTt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGg7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBtYXQyIHVfYW50aWFsaWFzaW5nbWF0cml4O3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxlO2Q9YV9kYXRhLnh5O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTt2ZWM0IGY9dmVjNCh1X2xpbmV3aWR0aC5zKmQqLjAxNTg3MzAxNiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoZmxvb3IoYV9wb3MqLjUpK2YueHkvdV9yYXRpbywwLDEpO2Zsb2F0IGcsaCxpO2c9Z2xfUG9zaXRpb24ueS9nbF9Qb3NpdGlvbi53O2g9bGVuZ3RoKGQpL2xlbmd0aCh1X2FudGlhbGlhc2luZ21hdHJpeCpkKTtpPTEuLygxLi1nKnVfZXh0cmEpO2M9aSpoO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGgsdV9kYXNoYXJyYXk7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2JsdXI7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiLGM7dm9pZCBtYWluKCl7ZmxvYXQgZCxlLGY7ZD1sZW5ndGgoYSkqdV9saW5ld2lkdGgucztlPXVfYmx1cipjO2Y9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtZSksdV9saW5ld2lkdGgucy1kKS9lLDAuLDEuKTtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJsaW5lcGF0dGVyblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW87dW5pZm9ybSB2ZWMyIHVfbGluZXdpZHRoO3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZSxmLGc7Yz1hX2RhdGEueHk7ZmxvYXQgZD1hX2RhdGEueioxMjguK2FfZGF0YS53O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTtmPWMqLjAxNTg3MzAxNjtnPXVfbGluZXdpZHRoLnMqZjtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPWQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5fc2l6ZV9hLHVfcGF0dGVybl9zaXplX2IsdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBmbG9hdCB1X3BvaW50LHVfYmx1cix1X2ZhZGUsdV9vcGFjaXR5O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiO3ZvaWQgbWFpbigpe2Zsb2F0IGMsZCxlLGYsZyxoO2M9bGVuZ3RoKGEpKnVfbGluZXdpZHRoLnM7ZD1jbGFtcChtaW4oYy0odV9saW5ld2lkdGgudC11X2JsdXIpLHVfbGluZXdpZHRoLnMtYykvdV9ibHVyLDAuLDEuKTtlPW1vZChiL3VfcGF0dGVybl9zaXplX2EueCwxLik7Zj1tb2QoYi91X3BhdHRlcm5fc2l6ZV9iLngsMS4pO2c9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYS55O2g9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYi55O3ZlYzIgaSxqO2k9bWl4KHVfcGF0dGVybl90bF9hLHVfcGF0dGVybl9icl9hLHZlYzIoZSxnKSk7aj1taXgodV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2IsdmVjMihmLGgpKTt2ZWM0IGs9bWl4KHRleHR1cmUyRCh1X2ltYWdlLGkpLHRleHR1cmUyRCh1X2ltYWdlLGopLHVfZmFkZSk7ZCo9dV9vcGFjaXR5O2dsX0ZyYWdDb2xvcj1rKmQ7fVwifSxcbiAgICBcImxpbmVzZGZwYXR0ZXJuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5zY2FsZV9hLHVfcGF0dGVybnNjYWxlX2I7dW5pZm9ybSBmbG9hdCB1X3JhdGlvLHVfdGV4X3lfYSx1X3RleF95X2I7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxmO2Q9YV9kYXRhLnh5O2Zsb2F0IGU9YV9kYXRhLnoqMTI4LithX2RhdGEudztmPW1vZChhX3BvcywyLik7Zi55PXNpZ24oZi55LS41KTthPWY7dmVjNCBnPXZlYzQodV9saW5ld2lkdGgucypkKi4wMTU4NzMwMTYsMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPXZlYzIoZSp1X3BhdHRlcm5zY2FsZV9hLngsZi55KnVfcGF0dGVybnNjYWxlX2EueSt1X3RleF95X2EpO2M9dmVjMihlKnVfcGF0dGVybnNjYWxlX2IueCxmLnkqdV9wYXR0ZXJuc2NhbGVfYi55K3VfdGV4X3lfYik7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDt1bmlmb3JtIHZlYzQgdV9jb2xvcjt1bmlmb3JtIGZsb2F0IHVfYmx1cix1X3NkZmdhbW1hLHVfbWl4O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmLGcsaDtkPWxlbmd0aChhKSp1X2xpbmV3aWR0aC5zO2U9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtdV9ibHVyKSx1X2xpbmV3aWR0aC5zLWQpL3VfYmx1ciwwLiwxLik7Zj10ZXh0dXJlMkQodV9pbWFnZSxiKS5hO2c9dGV4dHVyZTJEKHVfaW1hZ2UsYykuYTtoPW1peChmLGcsdV9taXgpO2UqPXNtb290aHN0ZXAoLjUtdV9zZGZnYW1tYSwuNSt1X3NkZmdhbW1hLGgpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmU7fVwifSxcbiAgICBcIm91dGxpbmVcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfd29ybGQ7dmFyeWluZyB2ZWMyIGE7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4pLzIuKnVfd29ybGQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZvaWQgbWFpbigpe2Zsb2F0IGIsYztiPWxlbmd0aChhLWdsX0ZyYWdDb29yZC54eSk7Yz1zbW9vdGhzdGVwKDEuLDAuLGIpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmM7fVwifSxcbiAgICBcInBhdHRlcm5cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBtYXQzIHVfcGF0dGVybm1hdHJpeF9hLHVfcGF0dGVybm1hdHJpeF9iO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KHVfcGF0dGVybm1hdHJpeF9hKnZlYzMoYV9wb3MsMSkpLnh5O2I9KHVfcGF0dGVybm1hdHJpeF9iKnZlYzMoYV9wb3MsMSkpLnh5O31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIGZsb2F0IHVfb3BhY2l0eSx1X21peDt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgYSxiO3ZvaWQgbWFpbigpe3ZlYzIgYyxkLGYsZztjPW1vZChhLDEuKTtkPW1peCh1X3BhdHRlcm5fdGxfYSx1X3BhdHRlcm5fYnJfYSxjKTt2ZWM0IGUsaDtlPXRleHR1cmUyRCh1X2ltYWdlLGQpO2Y9bW9kKGIsMS4pO2c9bWl4KHVfcGF0dGVybl90bF9iLHVfcGF0dGVybl9icl9iLGYpO2g9dGV4dHVyZTJEKHVfaW1hZ2UsZyk7Z2xfRnJhZ0NvbG9yPW1peChlLGgsdV9taXgpKnVfb3BhY2l0eTt9XCJ9LFxuICAgIFwicmFzdGVyXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3RsX3BhcmVudDt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfcGFyZW50LHVfYnVmZmVyX3NjYWxlO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfdGV4dHVyZV9wb3M7dmFyeWluZyB2ZWMyIGEsYjt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7YT0oYV90ZXh0dXJlX3Bvcy8zMjc2Ny4tLjUpL3VfYnVmZmVyX3NjYWxlKy41O2I9YSp1X3NjYWxlX3BhcmVudCt1X3RsX3BhcmVudDt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X29wYWNpdHkwLHVfb3BhY2l0eTEsdV9icmlnaHRuZXNzX2xvdyx1X2JyaWdodG5lc3NfaGlnaCx1X3NhdHVyYXRpb25fZmFjdG9yLHVfY29udHJhc3RfZmFjdG9yO3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2UwLHVfaW1hZ2UxO3ZhcnlpbmcgdmVjMiBhLGI7dW5pZm9ybSB2ZWMzIHVfc3Bpbl93ZWlnaHRzO3ZvaWQgbWFpbigpe3ZlYzQgYyxkLGU7Yz10ZXh0dXJlMkQodV9pbWFnZTAsYSk7ZD10ZXh0dXJlMkQodV9pbWFnZTEsYik7ZT1jKnVfb3BhY2l0eTArZCp1X29wYWNpdHkxO3ZlYzMgZixoLGk7Zj1lLnJnYjtmPXZlYzMoZG90KGYsdV9zcGluX3dlaWdodHMueHl6KSxkb3QoZix1X3NwaW5fd2VpZ2h0cy56eHkpLGRvdChmLHVfc3Bpbl93ZWlnaHRzLnl6eCkpO2Zsb2F0IGc9KGUucitlLmcrZS5iKS8zLjtmKz0oZy1mKSp1X3NhdHVyYXRpb25fZmFjdG9yO2Y9KGYtLjUpKnVfY29udHJhc3RfZmFjdG9yKy41O2g9dmVjMyh1X2JyaWdodG5lc3NfbG93KTtpPXZlYzModV9icmlnaHRuZXNzX2hpZ2gpO2dsX0ZyYWdDb2xvcj12ZWM0KG1peChoLGksZiksZS5hKTt9XCJ9LFxuICAgIFwiaWNvblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfb2Zmc2V0O2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTEsYV9kYXRhMjt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfem9vbSx1X2ZhZGVkaXN0LHVfbWluZmFkZXpvb20sdV9tYXhmYWRlem9vbSx1X2ZhZGV6b29tLHVfb3BhY2l0eSx1X2V4dHJhO3VuaWZvcm0gYm9vbCB1X3NrZXdlZDt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZTtjPWFfZGF0YTEueHk7ZmxvYXQgZCxmLGcsaCxpLGo7ZD1hX2RhdGExWzJdO2U9YV9kYXRhMi5zdDtmPWVbMF07Zz1lWzFdO2g9MTAuO2k9Mi4tc3RlcChmLHVfem9vbSktKDEuLXN0ZXAoZyx1X3pvb20pKTtqPWNsYW1wKCh1X2ZhZGV6b29tLWQpL3VfZmFkZWRpc3QsMC4sMS4pO2lmKHVfZmFkZWRpc3Q+PTAuKWI9ajtlbHNlIGI9MS4tajtpZih1X21heGZhZGV6b29tPGQpYj0wLjtpZih1X21pbmZhZGV6b29tPj1kKWI9MS47aSs9c3RlcChiLDAuKTtpZih1X3NrZXdlZCl7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4sMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zK2sueHksMCwxKTtnbF9Qb3NpdGlvbi56Kz1pKmdsX1Bvc2l0aW9uLnc7fWVsc2V7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4saSwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSkrazt9YT1jL3VfdGV4c2l6ZTtiKj11X29wYWNpdHk7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGI7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXRleHR1cmUyRCh1X3RleHR1cmUsYSkqYjt9XCJ9LFxuICAgIFwic2RmXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3MsYV9vZmZzZXQ7YXR0cmlidXRlIHZlYzQgYV9kYXRhMSxhX2RhdGEyO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gZmxvYXQgdV96b29tLHVfZmFkZWRpc3QsdV9taW5mYWRlem9vbSx1X21heGZhZGV6b29tLHVfZmFkZXpvb20sdV9leHRyYTt1bmlmb3JtIGJvb2wgdV9za2V3ZWQ7dW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGIsYzt2b2lkIG1haW4oKXt2ZWMyIGQsZjtkPWFfZGF0YTEueHk7ZmxvYXQgZSxnLGgsaSxqLGssbDtlPWFfZGF0YTFbMl07Zj1hX2RhdGEyLnN0O2c9ZlswXTtoPWZbMV07aT0yLi1zdGVwKGcsdV96b29tKS0oMS4tc3RlcChoLHVfem9vbSkpO2o9Y2xhbXAoKHVfZmFkZXpvb20tZSkvdV9mYWRlZGlzdCwwLiwxLik7aWYodV9mYWRlZGlzdD49MC4pYj1qO2Vsc2UgYj0xLi1qO2lmKHVfbWF4ZmFkZXpvb208ZSliPTAuO2lmKHVfbWluZmFkZXpvb20+PWUpYj0xLjtpKz1zdGVwKGIsMC4pO2lmKHVfc2tld2VkKXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3Mray54eSwwLDEpO2dsX1Bvc2l0aW9uLnorPWkqZ2xfUG9zaXRpb24udzt9ZWxzZXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LixpLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKStrO31rPWdsX1Bvc2l0aW9uLnkvZ2xfUG9zaXRpb24udztsPTEuLygxLi1rKnVfZXh0cmEpO2M9bDthPWQvdV90ZXhzaXplO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHNhbXBsZXIyRCB1X3RleHR1cmU7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2J1ZmZlcix1X2dhbW1hO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmO2Q9dV9nYW1tYSpjO2U9dGV4dHVyZTJEKHVfdGV4dHVyZSxhKS5hO2Y9c21vb3Roc3RlcCh1X2J1ZmZlci1kLHVfYnVmZmVyK2QsZSkqYjtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJjb2xsaXNpb25ib3hcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3BvcyxhX2V4dHJ1ZGUsYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfc2NhbGU7dmFyeWluZyBmbG9hdCBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcythX2V4dHJ1ZGUvdV9zY2FsZSwwLDEpO2E9YV9kYXRhLng7Yj1hX2RhdGEueTt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X3pvb20sdV9tYXh6b29tO3ZhcnlpbmcgZmxvYXQgYSxiO3ZvaWQgbWFpbigpe2Zsb2F0IGM9LjU7Z2xfRnJhZ0NvbG9yPXZlYzQoMCwxLDAsMSkqYztpZihiPnVfem9vbSlnbF9GcmFnQ29sb3I9dmVjNCgxLDAsMCwxKSpjO2lmKHVfem9vbT49YSlnbF9GcmFnQ29sb3I9dmVjNCgwLDAsMCwxKSpjKi4yNTtpZihiPj11X21heHpvb20pZ2xfRnJhZ0NvbG9yPXZlYzQoMCwwLDEsMSkqYyouMjt9XCJ9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQnKTtcbnZhciBUaWxlUHlyYW1pZCA9IHJlcXVpcmUoJy4vdGlsZV9weXJhbWlkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcbnZhciB1cmxSZXNvbHZlID0gcmVxdWlyZSgncmVzb2x2ZS11cmwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHZW9KU09OU291cmNlO1xuXG4vKipcbiAqIENyZWF0ZSBhIEdlb0pTT04gZGF0YSBzb3VyY2UgaW5zdGFuY2UgZ2l2ZW4gYW4gb3B0aW9ucyBvYmplY3RcbiAqIEBjbGFzcyBHZW9KU09OU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IG9wdGlvbnMuZGF0YSBBIEdlb0pTT04gZGF0YSBvYmplY3Qgb3IgVVJMIHRvIGl0LiBUaGUgbGF0dGVyIGlzIHByZWZlcmFibGUgaW4gY2FzZSBvZiBsYXJnZSBHZW9KU09OIGZpbGVzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heHpvb209MTRdIE1heGltdW0gem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgYXQuXG4gKiBAZXhhbXBsZVxuICogdmFyIHNvdXJjZU9iaiA9IG5ldyBtYXBib3hnbC5HZW9KU09OU291cmNlKHtcbiAqICAgIGRhdGE6IHtcbiAqICAgICAgICBcInR5cGVcIjogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICogICAgICAgIFwiZmVhdHVyZXNcIjogW3tcbiAqICAgICAgICAgICAgXCJ0eXBlXCI6IFwiRmVhdHVyZVwiLFxuICogICAgICAgICAgICBcImdlb21ldHJ5XCI6IHtcbiAqICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIlBvaW50XCIsXG4gKiAgICAgICAgICAgICAgICBcImNvb3JkaW5hdGVzXCI6IFtcbiAqICAgICAgICAgICAgICAgICAgICAtNzYuNTMwNjMyOTcyNzE3MjksXG4gKiAgICAgICAgICAgICAgICAgICAgMzkuMTgxNzQwNzc5OTQxMDhcbiAqICAgICAgICAgICAgICAgIF1cbiAqICAgICAgICAgICAgfVxuICogICAgICAgIH1dXG4gKiAgICB9XG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBHZW9KU09OU291cmNlKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIHRoaXMuX2RhdGEgPSBvcHRpb25zLmRhdGE7XG5cbiAgICBpZiAob3B0aW9ucy5tYXh6b29tICE9PSB1bmRlZmluZWQpIHRoaXMubWF4em9vbSA9IG9wdGlvbnMubWF4em9vbTtcblxuICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICB0aWxlU2l6ZTogNTEyLFxuICAgICAgICBtaW56b29tOiB0aGlzLm1pbnpvb20sXG4gICAgICAgIG1heHpvb206IHRoaXMubWF4em9vbSxcbiAgICAgICAgY2FjaGVTaXplOiAyMCxcbiAgICAgICAgbG9hZDogdGhpcy5fbG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICB1bmxvYWQ6IHRoaXMuX3VubG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWRkOiB0aGlzLl9hZGRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpXG4gICAgfSk7XG59XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEV2ZW50ZWQsIC8qKiBAbGVuZHMgR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUgKi97XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAxNCxcbiAgICBfZGlydHk6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgc291cmNlIGdlb2pzb24gZGF0YSBhbmQgcmVyZW5kZXIgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGRhdGEgQSBHZW9KU09OIGRhdGEgb2JqZWN0IG9yIFVSTCB0byBpdC4gVGhlIGxhdHRlciBpcyBwcmVmZXJhYmxlIGluIGNhc2Ugb2YgbGFyZ2UgR2VvSlNPTiBmaWxlcy5cbiAgICAgKiBAcmV0dXJucyB7R2VvSlNPTlNvdXJjZX0gdGhpc1xuICAgICAqL1xuICAgIHNldERhdGE6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScpO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcClcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHRoaXMubWFwLnRyYW5zZm9ybSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkZWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX2RpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEYXRhKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVuZGVyOiBTb3VyY2UuX3JlbmRlclRpbGVzLFxuICAgIGZlYXR1cmVzQXQ6IFNvdXJjZS5fdmVjdG9yRmVhdHVyZXNBdCxcblxuICAgIF91cGRhdGVEYXRhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkYXRhID0gdXJsUmVzb2x2ZSh3aW5kb3cubG9jYXRpb24uaHJlZiwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdwYXJzZSBnZW9qc29uJywge1xuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHRpbGVTaXplOiA1MTIsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb21cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyKSB7XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcblxuICAgICAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuXG4gICAgX2xvYWRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUuY29vcmQueiA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHRpbGUuY29vcmQueiAtIHRoaXMubWF4em9vbSkgOiAxO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgdWlkOiB0aWxlLnVpZCxcbiAgICAgICAgICAgIGNvb3JkOiB0aWxlLmNvb3JkLFxuICAgICAgICAgICAgem9vbTogdGlsZS5jb29yZC56LFxuICAgICAgICAgICAgbWF4Wm9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgdGlsZVNpemU6IDUxMixcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5pZCxcbiAgICAgICAgICAgIG92ZXJzY2FsaW5nOiBvdmVyc2NhbGluZyxcbiAgICAgICAgICAgIGFuZ2xlOiB0aGlzLm1hcC50cmFuc2Zvcm0uYW5nbGUsXG4gICAgICAgICAgICBwaXRjaDogdGhpcy5tYXAudHJhbnNmb3JtLnBpdGNoLFxuICAgICAgICAgICAgY29sbGlzaW9uRGVidWc6IHRoaXMubWFwLmNvbGxpc2lvbkRlYnVnXG4gICAgICAgIH07XG5cbiAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIGdlb2pzb24gdGlsZScsIHBhcmFtcywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG5cbiAgICAgICAgICAgIHRpbGUudW5sb2FkVmVjdG9yRGF0YSh0aGlzLm1hcC5wYWludGVyKTtcblxuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGlsZS5sb2FkVmVjdG9yRGF0YShkYXRhKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5sb2FkJywge3RpbGU6IHRpbGV9KTtcblxuICAgICAgICB9LmJpbmQodGhpcyksIHRoaXMud29ya2VySUQpO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCd2ZWN0b3ItdGlsZScpLlZlY3RvclRpbGVGZWF0dXJlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlb0pTT05XcmFwcGVyO1xuXG4vLyBjb25mb3JtIHRvIHZlY3RvcnRpbGUgYXBpXG5mdW5jdGlvbiBHZW9KU09OV3JhcHBlcihmZWF0dXJlcykge1xuICAgIHRoaXMuZmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICB0aGlzLmxlbmd0aCA9IGZlYXR1cmVzLmxlbmd0aDtcbn1cblxuR2VvSlNPTldyYXBwZXIucHJvdG90eXBlLmZlYXR1cmUgPSBmdW5jdGlvbihpKSB7XG4gICAgcmV0dXJuIG5ldyBGZWF0dXJlV3JhcHBlcih0aGlzLmZlYXR1cmVzW2ldKTtcbn07XG5cbmZ1bmN0aW9uIEZlYXR1cmVXcmFwcGVyKGZlYXR1cmUpIHtcbiAgICB0aGlzLnR5cGUgPSBmZWF0dXJlLnR5cGU7XG4gICAgdGhpcy5yYXdHZW9tZXRyeSA9IGZlYXR1cmUudHlwZSA9PT0gMSA/IFtmZWF0dXJlLmdlb21ldHJ5XSA6IGZlYXR1cmUuZ2VvbWV0cnk7XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gZmVhdHVyZS50YWdzO1xuICAgIHRoaXMuZXh0ZW50ID0gNDA5Njtcbn1cblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByaW5ncyA9IHRoaXMucmF3R2VvbWV0cnk7XG4gICAgdGhpcy5nZW9tZXRyeSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmluZyA9IHJpbmdzW2ldLFxuICAgICAgICAgICAgbmV3UmluZyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG5ld1JpbmcucHVzaChuZXcgUG9pbnQocmluZ1tqXVswXSwgcmluZ1tqXVsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2VvbWV0cnkucHVzaChuZXdSaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnk7XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5nZW9tZXRyeSkgdGhpcy5sb2FkR2VvbWV0cnkoKTtcblxuICAgIHZhciByaW5ncyA9IHRoaXMuZ2VvbWV0cnksXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjb29yZCA9IHJpbmdbal07XG5cbiAgICAgICAgICAgIHgxID0gTWF0aC5taW4oeDEsIGNvb3JkLngpO1xuICAgICAgICAgICAgeDIgPSBNYXRoLm1heCh4MiwgY29vcmQueCk7XG4gICAgICAgICAgICB5MSA9IE1hdGgubWluKHkxLCBjb29yZC55KTtcbiAgICAgICAgICAgIHkyID0gTWF0aC5tYXgoeTIsIGNvb3JkLnkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4MSwgeTEsIHgyLCB5Ml07XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUudG9HZW9KU09OID0gVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlJyk7XG52YXIgbm9ybWFsaXplVVJMID0gcmVxdWlyZSgnLi4vdXRpbC9tYXBib3gnKS5ub3JtYWxpemVUaWxlVVJMO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhc3RlclRpbGVTb3VyY2U7XG5cbmZ1bmN0aW9uIFJhc3RlclRpbGVTb3VyY2Uob3B0aW9ucykge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHV0aWwucGljayhvcHRpb25zLCBbJ3VybCcsICd0aWxlU2l6ZSddKSk7XG5cbiAgICBTb3VyY2UuX2xvYWRUaWxlSlNPTi5jYWxsKHRoaXMsIG9wdGlvbnMpO1xufVxuXG5SYXN0ZXJUaWxlU291cmNlLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChFdmVudGVkLCB7XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAyMixcbiAgICB0aWxlU2l6ZTogNTEyLFxuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB9LFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3B5cmFtaWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX3B5cmFtaWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5cmFtaWQudXBkYXRlKHRoaXMudXNlZCwgdHJhbnNmb3JtLCB0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcblxuICAgIF9sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBhamF4LmdldEltYWdlKG5vcm1hbGl6ZVVSTCh0aWxlLmNvb3JkLnVybCh0aGlzLnRpbGVzKSwgdGhpcy51cmwpLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGdsID0gdGhpcy5tYXAucGFpbnRlci5nbDtcbiAgICAgICAgICAgIHRpbGUudGV4dHVyZSA9IHRoaXMubWFwLnBhaW50ZXIuZ2V0VGV4dHVyZShpbWcud2lkdGgpO1xuICAgICAgICAgICAgaWYgKHRpbGUudGV4dHVyZSkge1xuICAgICAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRpbGUudGV4dHVyZSk7XG4gICAgICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCAwLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aWxlLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSX01JUE1BUF9ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGltZyk7XG4gICAgICAgICAgICAgICAgdGlsZS50ZXh0dXJlLnNpemUgPSBpbWcud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnbC5nZW5lcmF0ZU1pcG1hcChnbC5URVhUVVJFXzJEKTtcblxuICAgICAgICAgICAgdGlsZS50aW1lQWRkZWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHRoaXMubWFwLmFuaW1hdGlvbkxvb3Auc2V0KHRoaXMuc3R5bGUucmFzdGVyRmFkZUR1cmF0aW9uKTtcblxuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGlsZS5sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUubG9hZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9hYm9ydFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS5hYm9ydGVkID0gdHJ1ZTtcbiAgICB9LFxuXG4gICAgX2FkZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmFkZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmVUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5yZW1vdmUnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfdW5sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBpZiAodGlsZS50ZXh0dXJlKSB0aGlzLm1hcC5wYWludGVyLnNhdmVUZXh0dXJlKHRpbGUudGV4dHVyZSk7XG4gICAgfSxcblxuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFRpbGVQeXJhbWlkID0gcmVxdWlyZSgnLi90aWxlX3B5cmFtaWQnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBub3JtYWxpemVVUkwgPSByZXF1aXJlKCcuLi91dGlsL21hcGJveCcpLm5vcm1hbGl6ZVNvdXJjZVVSTDtcblxuZXhwb3J0cy5fbG9hZFRpbGVKU09OID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciBsb2FkZWQgPSBmdW5jdGlvbihlcnIsIHRpbGVKU09OKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKHRpbGVKU09OLFxuICAgICAgICAgICAgWyd0aWxlcycsICdtaW56b29tJywgJ21heHpvb20nLCAnYXR0cmlidXRpb24nXSkpO1xuXG4gICAgICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICAgICAgdGlsZVNpemU6IHRoaXMudGlsZVNpemUsXG4gICAgICAgICAgICBjYWNoZVNpemU6IDIwLFxuICAgICAgICAgICAgbWluem9vbTogdGhpcy5taW56b29tLFxuICAgICAgICAgICAgbWF4em9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgcmVwYXJzZU92ZXJzY2FsZWQ6IHRoaXMucmVwYXJzZU92ZXJzY2FsZWQsXG4gICAgICAgICAgICBsb2FkOiB0aGlzLl9sb2FkVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgdW5sb2FkOiB0aGlzLl91bmxvYWRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgICAgICBhZGQ6IHRoaXMuX2FkZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcmVkb1BsYWNlbWVudDogdGhpcy5fcmVkb1RpbGVQbGFjZW1lbnQgPyB0aGlzLl9yZWRvVGlsZVBsYWNlbWVudC5iaW5kKHRoaXMpIDogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmlyZSgnbG9hZCcpO1xuICAgIH0uYmluZCh0aGlzKTtcblxuICAgIGlmIChvcHRpb25zLnVybCkge1xuICAgICAgICBhamF4LmdldEpTT04obm9ybWFsaXplVVJMKG9wdGlvbnMudXJsKSwgbG9hZGVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBicm93c2VyLmZyYW1lKGxvYWRlZC5iaW5kKHRoaXMsIG51bGwsIG9wdGlvbnMpKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl9yZW5kZXJUaWxlcyA9IGZ1bmN0aW9uKGxheWVycywgcGFpbnRlcikge1xuICAgIGlmICghdGhpcy5fcHlyYW1pZClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQucmVuZGVyZWRJRHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3B5cmFtaWQuZ2V0VGlsZShpZHNbaV0pLFxuICAgICAgICAgICAgLy8gY29vcmQgaXMgZGlmZmVyZW50IHRoYW4gdGlsZS5jb29yZCBmb3Igd3JhcHBlZCB0aWxlcyBzaW5jZSB0aGUgYWN0dWFsXG4gICAgICAgICAgICAvLyB0aWxlIG9iamVjdCBpcyBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlIHZpc2libGUgY29waWVzIG9mIHRoYXQgdGlsZS5cbiAgICAgICAgICAgIGNvb3JkID0gVGlsZUNvb3JkLmZyb21JRChpZHNbaV0pLFxuICAgICAgICAgICAgeiA9IGNvb3JkLnosXG4gICAgICAgICAgICB4ID0gY29vcmQueCxcbiAgICAgICAgICAgIHkgPSBjb29yZC55LFxuICAgICAgICAgICAgdyA9IGNvb3JkLnc7XG5cbiAgICAgICAgLy8gaWYgeiA+IG1heHpvb20gdGhlbiB0aGUgdGlsZSBpcyBhY3R1YWxseSBhIG92ZXJzY2FsZWQgbWF4em9vbSB0aWxlLFxuICAgICAgICAvLyBzbyBjYWxjdWxhdGUgdGhlIG1hdHJpeCB0aGUgbWF4em9vbSB0aWxlIHdvdWxkIHVzZS5cbiAgICAgICAgeiA9IE1hdGgubWluKHosIHRoaXMubWF4em9vbSk7XG5cbiAgICAgICAgeCArPSB3ICogKDEgPDwgeik7XG4gICAgICAgIHRpbGUuY2FsY3VsYXRlTWF0cmljZXMoeiwgeCwgeSwgcGFpbnRlci50cmFuc2Zvcm0sIHBhaW50ZXIpO1xuXG4gICAgICAgIHBhaW50ZXIuZHJhd1RpbGUodGlsZSwgbGF5ZXJzKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl92ZWN0b3JGZWF0dXJlc0F0ID0gZnVuY3Rpb24oY29vcmQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuX3B5cmFtaWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBbXSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gdGhpcy5fcHlyYW1pZC50aWxlQXQoY29vcmQpO1xuICAgIGlmICghcmVzdWx0KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuXG4gICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3F1ZXJ5IGZlYXR1cmVzJywge1xuICAgICAgICB1aWQ6IHJlc3VsdC50aWxlLnVpZCxcbiAgICAgICAgeDogcmVzdWx0LngsXG4gICAgICAgIHk6IHJlc3VsdC55LFxuICAgICAgICBzY2FsZTogcmVzdWx0LnNjYWxlLFxuICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfSwgY2FsbGJhY2ssIHJlc3VsdC50aWxlLndvcmtlcklEKTtcbn07XG5cbi8qXG4gKiBDcmVhdGUgYSB0aWxlZCBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50eXBlIEVpdGhlciBgcmFzdGVyYCBvciBgdmVjdG9yYC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCBBIHRpbGUgc291cmNlIFVSTC4gVGhpcyBzaG91bGQgZWl0aGVyIGJlIGBtYXBib3g6Ly97bWFwaWR9YCBvciBhIGZ1bGwgYGh0dHBbc11gIHVybCB0aGF0IHBvaW50cyB0byBhIFRpbGVKU09OIGVuZHBvaW50LlxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy50aWxlcyBBbiBhcnJheSBvZiB0aWxlIHNvdXJjZXMuIElmIGB1cmxgIGlzIG5vdCBzcGVjaWZpZWQsIGB0aWxlc2AgY2FuIGJlIHVzZWQgaW5zdGVhZCB0byBzcGVjaWZ5IHRpbGUgc291cmNlcywgYXMgaW4gdGhlIFRpbGVKU09OIHNwZWMuIE90aGVyIFRpbGVKU09OIGtleXMgc3VjaCBhcyBgbWluem9vbWAgYW5kIGBtYXh6b29tYCBjYW4gYmUgc3BlY2lmaWVkIGluIGEgc291cmNlIG9iamVjdCBpZiBgdGlsZXNgIGlzIHVzZWQuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5pZCBBbiBvcHRpb25hbCBgaWRgIHRvIGFzc2lnbiB0byB0aGUgc291cmNlXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGlsZVNpemU9NTEyXSBPcHRpb25hbCB0aWxlIHNpemUgKHdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzLCBhc3N1bWluZyB0aWxlcyBhcmUgc3F1YXJlKS4gVGhpcyBvcHRpb24gaXMgb25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBzb3VyY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5jYWNoZVNpemUgT3B0aW9uYWwgbWF4IG51bWJlciBvZiB0aWxlcyB0byBjYWNoZSBhdCBhbnkgZ2l2ZW4gdGltZVxuICogQGV4YW1wbGVcbiAqIHZhciBzb3VyY2VPYmogPSBuZXcgbWFwYm94Z2wuU291cmNlLmNyZWF0ZSh7XG4gKiAgICB0eXBlOiAndmVjdG9yJyxcbiAqICAgIHVybDogJ21hcGJveDovL21hcGJveC5tYXBib3gtc3RyZWV0cy12NSdcbiAqIH0pO1xuICogbWFwLmFkZFNvdXJjZSgnc29tZSBpZCcsIHNvdXJjZU9iaik7IC8vIGFkZFxuICogbWFwLnJlbW92ZVNvdXJjZSgnc29tZSBpZCcpOyAgLy8gcmVtb3ZlXG4gKi9cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24oc291cmNlKSB7XG4gICAgLy8gVGhpcyBpcyBub3QgYXQgZmlsZSBzY29wZSBpbiBvcmRlciB0byBhdm9pZCBhIGNpcmN1bGFyIHJlcXVpcmUuXG4gICAgdmFyIHNvdXJjZXMgPSB7XG4gICAgICAgIHZlY3RvcjogcmVxdWlyZSgnLi92ZWN0b3JfdGlsZV9zb3VyY2UnKSxcbiAgICAgICAgcmFzdGVyOiByZXF1aXJlKCcuL3Jhc3Rlcl90aWxlX3NvdXJjZScpLFxuICAgICAgICBnZW9qc29uOiByZXF1aXJlKCcuL2dlb2pzb25fc291cmNlJyksXG4gICAgICAgIHZpZGVvOiByZXF1aXJlKCcuL3ZpZGVvX3NvdXJjZScpXG4gICAgfTtcblxuICAgIGZvciAodmFyIHR5cGUgaW4gc291cmNlcykge1xuICAgICAgICBpZiAoc291cmNlIGluc3RhbmNlb2Ygc291cmNlc1t0eXBlXSkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgc291cmNlc1tzb3VyY2UudHlwZV0oc291cmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpO1xudmFyIG1hdDIgPSBnbG1hdHJpeC5tYXQyO1xudmFyIG1hdDQgPSBnbG1hdHJpeC5tYXQ0O1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXJTZXQgPSByZXF1aXJlKCcuLi9kYXRhL2J1ZmZlci9idWZmZXJfc2V0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZTtcblxuLyoqXG4gKiBBIHRpbGUgb2JqZWN0IGlzIHRoZSBjb21iaW5hdGlvbiBvZiBhIENvb3JkaW5hdGUsIHdoaWNoIGRlZmluZXNcbiAqIGl0cyBwbGFjZSwgYXMgd2VsbCBhcyBhIHVuaXF1ZSBJRCBhbmQgZGF0YSB0cmFja2luZyBmb3IgaXRzIGNvbnRlbnRcbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZVxuICovXG5mdW5jdGlvbiBUaWxlKGNvb3JkLCBzaXplKSB7XG4gICAgdGhpcy5jb29yZCA9IGNvb3JkO1xuICAgIHRoaXMudWlkID0gdXRpbC51bmlxdWVJZCgpO1xuICAgIHRoaXMubG9hZGVkID0gZmFsc2U7XG4gICAgdGhpcy51c2VzID0gMDtcbiAgICB0aGlzLnRpbGVTaXplID0gc2l6ZTtcbn1cblxuVGlsZS5wcm90b3R5cGUgPSB7XG4gICAgLy8gdG9kbyB1bmhhcmRjb2RlXG4gICAgdGlsZUV4dGVudDogNDA5NixcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgaW50ZXJuYWwgcG9zTWF0cml4IHRoYXQgdGhpcyB0aWxlIHVzZXMgdG8gZGlzcGxheVxuICAgICAqIGl0c2VsZiBpbiBhIG1hcCwgZ2l2ZW4gYSBjb29yZGluYXRlIGFzICh6LCB4LCB5KSBhbmQgYSB0cmFuc2Zvcm1cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gelxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICovXG4gICAgY2FsY3VsYXRlTWF0cmljZXM6IGZ1bmN0aW9uKHosIHgsIHksIHRyYW5zZm9ybSkge1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgbW9kZWwtdmlldyBtYXRyaXggdGhhdCBjb252ZXJ0cyBmcm9tIHRoZSB0aWxlIGNvb3JkaW5hdGVzXG4gICAgICAgIC8vIHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAgICAgICAgdmFyIHRpbGVTY2FsZSA9IE1hdGgucG93KDIsIHopO1xuICAgICAgICB2YXIgc2NhbGUgPSB0cmFuc2Zvcm0ud29ybGRTaXplIC8gdGlsZVNjYWxlO1xuXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZVxuICAgICAgICB0aGlzLnNjYWxlID0gc2NhbGU7XG5cbiAgICAgICAgLy8gVGhlIHBvc2l0aW9uIG1hdHJpeFxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDY0QXJyYXkoMTYpO1xuICAgICAgICBtYXQ0LmlkZW50aXR5KHRoaXMucG9zTWF0cml4KTtcbiAgICAgICAgbWF0NC50cmFuc2xhdGUodGhpcy5wb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4LCBbeCAqIHNjYWxlLCB5ICogc2NhbGUsIDBdKTtcblxuICAgICAgICBtYXQ0LnNjYWxlKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgWyBzY2FsZSAvIHRoaXMudGlsZUV4dGVudCwgc2NhbGUgLyB0aGlzLnRpbGVFeHRlbnQsIDEgXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkodGhpcy5wb3NNYXRyaXgsIHRyYW5zZm9ybS5nZXRQcm9qTWF0cml4KCksIHRoaXMucG9zTWF0cml4KTtcblxuICAgICAgICAvLyBUaGUgZXh0cnVzaW9uIG1hdHJpeC5cbiAgICAgICAgdGhpcy5leE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIG1hdDQub3J0aG8odGhpcy5leE1hdHJpeCwgMCwgdHJhbnNmb3JtLndpZHRoLCB0cmFuc2Zvcm0uaGVpZ2h0LCAwLCAwLCAtMSk7XG4gICAgICAgIC8vbWF0NC5yb3RhdGVaKHRoaXMuZXhNYXRyaXgsIHRoaXMuZXhNYXRyaXgsIC10cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgICAgIC8vIDJ4MiBtYXRyaXggZm9yIHJvdGF0aW5nIHBvaW50c1xuICAgICAgICB0aGlzLnJvdGF0aW9uTWF0cml4ID0gbWF0Mi5jcmVhdGUoKTtcbiAgICAgICAgbWF0Mi5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCwgdGhpcy5yb3RhdGlvbk1hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcblxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5wb3NNYXRyaXgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGNvb3JkaW5hdGUgcG9zaXRpb24sIHpvb20gdGhhdCBjb29yZGluYXRlIHRvIG15IHpvb20gYW5kXG4gICAgICogc2NhbGUgYW5kIHJldHVybiBhIHBvc2l0aW9uIGluIHgsIHksIHNjYWxlXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHBvc2l0aW9uXG4gICAgICovXG4gICAgcG9zaXRpb25BdDogZnVuY3Rpb24oY29vcmQsIHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgY29vcmQgPSBjb29yZC56b29tVG8oTWF0aC5taW4odGhpcy5jb29yZC56LCBzb3VyY2VNYXhab29tKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiAoY29vcmQuY29sdW1uIC0gdGhpcy5jb29yZC54KSAqIDQwOTYsXG4gICAgICAgICAgICB5OiAoY29vcmQucm93IC0gdGhpcy5jb29yZC55KSAqIDQwOTYsXG4gICAgICAgICAgICBzY2FsZTogdGhpcy5zY2FsZVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGRhdGEgb2JqZWN0IHdpdGggYSAnYnVmZmVycycgcHJvcGVydHksIGxvYWQgaXQgaW50b1xuICAgICAqIHRoaXMgdGlsZSdzIGVsZW1lbnRHcm91cHMgYW5kIGJ1ZmZlcnMgcHJvcGVydGllcyBhbmQgc2V0IGxvYWRlZFxuICAgICAqIHRvIHRydWUuIElmIHRoZSBkYXRhIGlzIG51bGwsIGxpa2UgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHlcbiAgICAgKiBHZW9KU09OIHRpbGUsIG5vLW9wIGJ1dCBzdGlsbCBzZXQgbG9hZGVkIHRvIHRydWUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBlbXB0eSBHZW9KU09OIHRpbGVcbiAgICAgICAgaWYgKCFkYXRhKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXJzID0gbmV3IEJ1ZmZlclNldChkYXRhLmJ1ZmZlcnMpO1xuICAgICAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBkYXRhLmVsZW1lbnRHcm91cHM7XG4gICAgICAgIHRoaXMudGlsZUV4dGVudCA9IGRhdGEuZXh0ZW50O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBnaXZlbiBhIGRhdGEgb2JqZWN0IGFuZCBhIEdMIHBhaW50ZXIsIGRlc3Ryb3kgYW5kIHJlLWNyZWF0ZVxuICAgICAqIGFsbCBvZiBpdHMgYnVmZmVycy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyXG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICByZWxvYWRTeW1ib2xEYXRhOiBmdW5jdGlvbihkYXRhLCBwYWludGVyKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIC8vIHRoZSB0aWxlIGhhcyBiZWVuIGRlc3Ryb3llZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5nbHlwaEVsZW1lbnQuZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25WZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcblxuICAgICAgICB2YXIgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoZGF0YS5idWZmZXJzKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4ID0gYnVmZmVycy5nbHlwaFZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoRWxlbWVudCA9IGJ1ZmZlcnMuZ2x5cGhFbGVtZW50O1xuICAgICAgICB0aGlzLmJ1ZmZlcnMuaWNvblZlcnRleCA9IGJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50ID0gYnVmZmVycy5pY29uRWxlbWVudDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmNvbGxpc2lvbkJveFZlcnRleCA9IGJ1ZmZlcnMuY29sbGlzaW9uQm94VmVydGV4O1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzW2lkXSA9IGRhdGEuZWxlbWVudEdyb3Vwc1tpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWFrZSBzdXJlIHRoYXQgdGhpcyB0aWxlIGRvZXNuJ3Qgb3duIGFueSBkYXRhIHdpdGhpbiBhIGdpdmVuXG4gICAgICogcGFpbnRlciwgc28gdGhhdCBpdCBkb2Vzbid0IGNvbnN1bWUgYW55IG1lbW9yeSBvciBtYWludGFpblxuICAgICAqIGFueSByZWZlcmVuY2VzIHRvIHRoZSBwYWludGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyIGdsIHBhaW50ZXIgb2JqZWN0XG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB1bmxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihwYWludGVyKSB7XG4gICAgICAgIGZvciAodmFyIGIgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlcnNbYl0uZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSBudWxsO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZUNvb3JkO1xuXG5mdW5jdGlvbiBUaWxlQ29vcmQoeiwgeCwgeSwgdykge1xuICAgIGlmICh3ID09PSB1bmRlZmluZWQpIHcgPSAwO1xuICAgIHRoaXMueiA9IHo7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMudyA9IHc7XG5cbiAgICAvLyBjYWxjdWxhdGUgaWRcbiAgICB3ICo9IDI7XG4gICAgaWYgKHcgPCAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB2YXIgZGltID0gMSA8PCB0aGlzLno7XG4gICAgdGhpcy5pZCA9ICgoZGltICogZGltICogdyArIGRpbSAqIHRoaXMueSArIHRoaXMueCkgKiAzMikgKyB0aGlzLno7XG59XG5cblRpbGVDb29yZC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy56ICsgXCIvXCIgKyB0aGlzLnggKyBcIi9cIiArIHRoaXMueTtcbn07XG5cbi8vIFBhcnNlIGEgcGFja2VkIGludGVnZXIgaWQgaW50byBhIFRpbGVDb29yZCBvYmplY3RcblRpbGVDb29yZC5mcm9tSUQgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciB6ID0gaWQgJSAzMiwgZGltID0gMSA8PCB6O1xuICAgIHZhciB4eSA9ICgoaWQgLSB6KSAvIDMyKTtcbiAgICB2YXIgeCA9IHh5ICUgZGltLCB5ID0gKCh4eSAtIHgpIC8gZGltKSAlIGRpbTtcbiAgICB2YXIgdyA9IE1hdGguZmxvb3IoeHkgLyAoZGltICogZGltKSk7XG4gICAgaWYgKHcgJSAyICE9PSAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB3IC89IDI7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQoeiwgeCwgeSwgdyk7XG59O1xuXG4vLyBnaXZlbiBhIGxpc3Qgb2YgdXJscywgY2hvb3NlIGEgdXJsIHRlbXBsYXRlIGFuZCByZXR1cm4gYSB0aWxlIFVSTFxuVGlsZUNvb3JkLnByb3RvdHlwZS51cmwgPSBmdW5jdGlvbih1cmxzLCBzb3VyY2VNYXhab29tKSB7XG4gICAgcmV0dXJuIHVybHNbKHRoaXMueCArIHRoaXMueSkgJSB1cmxzLmxlbmd0aF1cbiAgICAgICAgLnJlcGxhY2UoJ3twcmVmaXh9JywgKHRoaXMueCAlIDE2KS50b1N0cmluZygxNikgKyAodGhpcy55ICUgMTYpLnRvU3RyaW5nKDE2KSlcbiAgICAgICAgLnJlcGxhY2UoJ3t6fScsIE1hdGgubWluKHRoaXMueiwgc291cmNlTWF4Wm9vbSB8fCB0aGlzLnopKVxuICAgICAgICAucmVwbGFjZSgne3h9JywgdGhpcy54KVxuICAgICAgICAucmVwbGFjZSgne3l9JywgdGhpcy55KTtcbn07XG5cbi8vIFJldHVybiB0aGUgY29vcmRpbmF0ZSBvZiB0aGUgcGFyZW50IHRpbGVcblRpbGVDb29yZC5wcm90b3R5cGUucGFyZW50ID0gZnVuY3Rpb24oc291cmNlTWF4Wm9vbSkge1xuICAgIGlmICh0aGlzLnogPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgLy8gdGhlIGlkIHJlcHJlc2VudHMgYW4gb3ZlcnNjYWxlZCB0aWxlLCByZXR1cm4gdGhlIHNhbWUgY29vcmRpbmF0ZXMgd2l0aCBhIGxvd2VyIHpcbiAgICBpZiAodGhpcy56ID4gc291cmNlTWF4Wm9vbSkge1xuICAgICAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCBNYXRoLmZsb29yKHRoaXMueCAvIDIpLCBNYXRoLmZsb29yKHRoaXMueSAvIDIpLCB0aGlzLncpO1xufTtcblxuVGlsZUNvb3JkLnByb3RvdHlwZS53cmFwcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQodGhpcy56LCB0aGlzLngsIHRoaXMueSwgMCk7XG59O1xuXG4vLyBSZXR1cm4gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB0aWxlJ3MgY2hpbGRyZW5cblRpbGVDb29yZC5wcm90b3R5cGUuY2hpbGRyZW4gPSBmdW5jdGlvbihzb3VyY2VNYXhab29tKSB7XG5cbiAgICBpZiAodGhpcy56ID49IHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgLy8gcmV0dXJuIGEgc2luZ2xlIHRpbGUgY29vcmQgcmVwcmVzZW50aW5nIGEgYW4gb3ZlcnNjYWxlZCB0aWxlXG4gICAgICAgIHJldHVybiBbbmV3IFRpbGVDb29yZCh0aGlzLnogKyAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KV07XG4gICAgfVxuXG4gICAgdmFyIHogPSB0aGlzLnogKyAxO1xuICAgIHZhciB4ID0gdGhpcy54ICogMjtcbiAgICB2YXIgeSA9IHRoaXMueSAqIDI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IFRpbGVDb29yZCh6LCB4LCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHgsIHkgKyAxLCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5ICsgMSwgdGhpcy53KVxuICAgIF07XG59O1xuXG4vLyBUYWtlbiBmcm9tIHBvbHltYXBzIHNyYy9MYXllci5qc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3NpbXBsZWdlby9wb2x5bWFwcy9ibG9iL21hc3Rlci9zcmMvTGF5ZXIuanMjTDMzMy1MMzgzXG5cbmZ1bmN0aW9uIGVkZ2UoYSwgYikge1xuICAgIGlmIChhLnJvdyA+IGIucm93KSB7IHZhciB0ID0gYTsgYSA9IGI7IGIgPSB0OyB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDA6IGEuY29sdW1uLFxuICAgICAgICB5MDogYS5yb3csXG4gICAgICAgIHgxOiBiLmNvbHVtbixcbiAgICAgICAgeTE6IGIucm93LFxuICAgICAgICBkeDogYi5jb2x1bW4gLSBhLmNvbHVtbixcbiAgICAgICAgZHk6IGIucm93IC0gYS5yb3dcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBzY2FuU3BhbnMoZTAsIGUxLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciB5MCA9IE1hdGgubWF4KHltaW4sIE1hdGguZmxvb3IoZTEueTApKTtcbiAgICB2YXIgeTEgPSBNYXRoLm1pbih5bWF4LCBNYXRoLmNlaWwoZTEueTEpKTtcblxuICAgIC8vIHNvcnQgZWRnZXMgYnkgeC1jb29yZGluYXRlXG4gICAgaWYgKChlMC54MCA9PT0gZTEueDAgJiYgZTAueTAgPT09IGUxLnkwKSA/XG4gICAgICAgICAgICAoZTAueDAgKyBlMS5keSAvIGUwLmR5ICogZTAuZHggPCBlMS54MSkgOlxuICAgICAgICAgICAgKGUwLngxIC0gZTEuZHkgLyBlMC5keSAqIGUwLmR4IDwgZTEueDApKSB7XG4gICAgICAgIHZhciB0ID0gZTA7IGUwID0gZTE7IGUxID0gdDtcbiAgICB9XG5cbiAgICAvLyBzY2FuIGxpbmVzIVxuICAgIHZhciBtMCA9IGUwLmR4IC8gZTAuZHk7XG4gICAgdmFyIG0xID0gZTEuZHggLyBlMS5keTtcbiAgICB2YXIgZDAgPSBlMC5keCA+IDA7IC8vIHVzZSB5ICsgMSB0byBjb21wdXRlIHgwXG4gICAgdmFyIGQxID0gZTEuZHggPCAwOyAvLyB1c2UgeSArIDEgdG8gY29tcHV0ZSB4MVxuICAgIGZvciAodmFyIHkgPSB5MDsgeSA8IHkxOyB5KyspIHtcbiAgICAgICAgdmFyIHgwID0gbTAgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMC5keSwgeSArIGQwIC0gZTAueTApKSArIGUwLngwO1xuICAgICAgICB2YXIgeDEgPSBtMSAqIE1hdGgubWF4KDAsIE1hdGgubWluKGUxLmR5LCB5ICsgZDEgLSBlMS55MCkpICsgZTEueDA7XG4gICAgICAgIHNjYW5MaW5lKE1hdGguZmxvb3IoeDEpLCBNYXRoLmNlaWwoeDApLCB5KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNjYW5UcmlhbmdsZShhLCBiLCBjLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciBhYiA9IGVkZ2UoYSwgYiksXG4gICAgICAgIGJjID0gZWRnZShiLCBjKSxcbiAgICAgICAgY2EgPSBlZGdlKGMsIGEpO1xuXG4gICAgdmFyIHQ7XG5cbiAgICAvLyBzb3J0IGVkZ2VzIGJ5IHktbGVuZ3RoXG4gICAgaWYgKGFiLmR5ID4gYmMuZHkpIHsgdCA9IGFiOyBhYiA9IGJjOyBiYyA9IHQ7IH1cbiAgICBpZiAoYWIuZHkgPiBjYS5keSkgeyB0ID0gYWI7IGFiID0gY2E7IGNhID0gdDsgfVxuICAgIGlmIChiYy5keSA+IGNhLmR5KSB7IHQgPSBiYzsgYmMgPSBjYTsgY2EgPSB0OyB9XG5cbiAgICAvLyBzY2FuIHNwYW4hIHNjYW4gc3BhbiFcbiAgICBpZiAoYWIuZHkpIHNjYW5TcGFucyhjYSwgYWIsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbiAgICBpZiAoYmMuZHkpIHNjYW5TcGFucyhjYSwgYmMsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbn1cblxuVGlsZUNvb3JkLmNvdmVyID0gZnVuY3Rpb24oeiwgYm91bmRzLCBhY3R1YWxaKSB7XG4gICAgdmFyIHRpbGVzID0gMSA8PCB6O1xuICAgIHZhciB0ID0ge307XG5cbiAgICBmdW5jdGlvbiBzY2FuTGluZSh4MCwgeDEsIHkpIHtcbiAgICAgICAgdmFyIHgsIHd4O1xuICAgICAgICBpZiAoeSA+PSAwICYmIHkgPD0gdGlsZXMpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IHgwOyB4IDwgeDE7IHgrKykge1xuICAgICAgICAgICAgICAgIHd4ID0gKHggKyB0aWxlcykgJSB0aWxlcztcbiAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBuZXcgVGlsZUNvb3JkKGFjdHVhbFosIHd4LCB5LCBNYXRoLmZsb29yKHggLyB0aWxlcykpO1xuICAgICAgICAgICAgICAgIHRbY29vcmQuaWRdID0gY29vcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXZpZGUgdGhlIHNjcmVlbiB1cCBpbiB0d28gdHJpYW5nbGVzIGFuZCBzY2FuIGVhY2ggb2YgdGhlbTpcbiAgICAvLyArLS0tL1xuICAgIC8vIHwgLyB8XG4gICAgLy8gLy0tLStcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzBdLCBib3VuZHNbMV0sIGJvdW5kc1syXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzJdLCBib3VuZHNbM10sIGJvdW5kc1swXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0KS5tYXAoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRbaWRdO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQ2FjaGUgPSByZXF1aXJlKCcuLi91dGlsL21ydV9jYWNoZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUaWxlUHlyYW1pZDtcblxuLyoqXG4gKiBBIHRpbGUgcHlyYW1pZCBpcyBhIHNwZWNpYWxpemVkIGNhY2hlIGFuZCBkYXRhc3RydWN0dXJlXG4gKiB0aGF0IGNvbnRhaW5zIHRpbGVzLiBJdCdzIHVzZWQgYnkgc291cmNlcyB0byBtYW5hZ2UgdGhlaXJcbiAqIGRhdGEuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnRpbGVTaXplXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5taW56b29tXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5tYXh6b29tXG4gKi9cbmZ1bmN0aW9uIFRpbGVQeXJhbWlkKG9wdGlvbnMpIHtcbiAgICB0aGlzLnRpbGVTaXplID0gb3B0aW9ucy50aWxlU2l6ZTtcbiAgICB0aGlzLm1pbnpvb20gPSBvcHRpb25zLm1pbnpvb207XG4gICAgdGhpcy5tYXh6b29tID0gb3B0aW9ucy5tYXh6b29tO1xuICAgIHRoaXMucmVwYXJzZU92ZXJzY2FsZWQgPSBvcHRpb25zLnJlcGFyc2VPdmVyc2NhbGVkO1xuXG4gICAgdGhpcy5fbG9hZCA9IG9wdGlvbnMubG9hZDtcbiAgICB0aGlzLl9hYm9ydCA9IG9wdGlvbnMuYWJvcnQ7XG4gICAgdGhpcy5fdW5sb2FkID0gb3B0aW9ucy51bmxvYWQ7XG4gICAgdGhpcy5fYWRkID0gb3B0aW9ucy5hZGQ7XG4gICAgdGhpcy5fcmVtb3ZlID0gb3B0aW9ucy5yZW1vdmU7XG4gICAgdGhpcy5fcmVkb1BsYWNlbWVudCA9IG9wdGlvbnMucmVkb1BsYWNlbWVudDtcblxuICAgIHRoaXMuX3RpbGVzID0ge307XG4gICAgdGhpcy5fY2FjaGUgPSBuZXcgQ2FjaGUob3B0aW9ucy5jYWNoZVNpemUsIGZ1bmN0aW9uKHRpbGUpIHsgcmV0dXJuIHRoaXMuX3VubG9hZCh0aWxlKTsgfS5iaW5kKHRoaXMpKTtcbn1cblxuVGlsZVB5cmFtaWQucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIENvbmZpcm0gdGhhdCBldmVyeSB0cmFja2VkIHRpbGUgaXMgbG9hZGVkLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIGFsbCB0aWxlcyBhcmUgbG9hZGVkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgdCBpbiB0aGlzLl90aWxlcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl90aWxlc1t0XS5sb2FkZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRpbGUgaWRzIG9yZGVyZWQgd2l0aCB6LW9yZGVyLCBhbmQgY2FzdCB0byBudW1iZXJzXG4gICAgICogQHJldHVybnMge0FycmF5PG51bWJlcj59IGlkc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgb3JkZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl90aWxlcylcbiAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIChiICUgMzIpIC0gKGEgJSAzMik7IH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGlkKSB7IHJldHVybiAraWQ7IH0pO1xuICAgIH0sXG5cbiAgICByZW5kZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yZGVyZWRJRHMoKS5maWx0ZXIoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90aWxlc1tpZF0ubG9hZGVkICYmICF0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICByZWxvYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9jYWNoZS5yZXNldCgpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMuX3RpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2FkKHRoaXMuX3RpbGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzcGVjaWZpYyB0aWxlIGJ5IGlkXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCB0aWxlIGlkXG4gICAgICogQHJldHVybnMge09iamVjdH0gdGlsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0VGlsZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RpbGVzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogZ2V0IHRoZSB6b29tIGxldmVsIGFkanVzdGVkIGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtYXAgYW5kIHNvdXJjZSB0aWxlc2l6ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICogQHJldHVybnMge251bWJlcn0gem9vbSBsZXZlbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm0uem9vbSArIE1hdGgubG9nKHRyYW5zZm9ybS50aWxlU2l6ZSAvIHRoaXMudGlsZVNpemUpIC8gTWF0aC5MTjI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHpvb20gbGV2ZWwgdGhhdCB3aWxsIGNvdmVyIGFsbCB0aWxlcyBpbiBhIGdpdmVuIHRyYW5zZm9ybVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSB6b29tIGxldmVsXG4gICAgICovXG4gICAgY292ZXJpbmdab29tTGV2ZWw6IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldFpvb20odHJhbnNmb3JtKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgdHJhbnNmb3JtLCByZXR1cm4gYWxsIGNvb3JkaW5hdGVzIHRoYXQgY291bGQgY292ZXIgdGhhdFxuICAgICAqIHRyYW5zZm9ybSBmb3IgYSBjb3ZlcmluZyB6b29tIGxldmVsLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8VGlsZT59IHRpbGVzXG4gICAgICovXG4gICAgY292ZXJpbmdUaWxlczogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHZhciB6ID0gdGhpcy5jb3ZlcmluZ1pvb21MZXZlbCh0cmFuc2Zvcm0pO1xuICAgICAgICB2YXIgYWN0dWFsWiA9IHo7XG5cbiAgICAgICAgaWYgKHogPCB0aGlzLm1pbnpvb20pIHJldHVybiBbXTtcbiAgICAgICAgaWYgKHogPiB0aGlzLm1heHpvb20pIHogPSB0aGlzLm1heHpvb207XG5cbiAgICAgICAgdmFyIHRyID0gdHJhbnNmb3JtLFxuICAgICAgICAgICAgdGlsZUNlbnRlciA9IHRyLmxvY2F0aW9uQ29vcmRpbmF0ZSh0ci5jZW50ZXIpLl96b29tVG8oeiksXG4gICAgICAgICAgICBjZW50ZXJQb2ludCA9IG5ldyBQb2ludCh0aWxlQ2VudGVyLmNvbHVtbiAtIDAuNSwgdGlsZUNlbnRlci5yb3cgLSAwLjUpO1xuXG4gICAgICAgIHJldHVybiBUaWxlQ29vcmQuY292ZXIoeiwgW1xuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCgwLCAwKSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQodHIud2lkdGgsIDApKS5fem9vbVRvKHopLFxuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCh0ci53aWR0aCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQoMCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KVxuICAgICAgICBdLCB0aGlzLnJlcGFyc2VPdmVyc2NhbGVkID8gYWN0dWFsWiA6IHopLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGNlbnRlclBvaW50LmRpc3QoYSkgLSBjZW50ZXJQb2ludC5kaXN0KGIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmluZCBjaGlsZHJlbiBvZiB0aGUgZ2l2ZW4gdGlsZSAodXAgdG8gbWF4Q292ZXJpbmdab29tKSB0aGF0IGFyZSBhbHJlYWR5IGxvYWRlZDtcbiAgICAgKiBhZGRzIGZvdW5kIHRpbGVzIHRvIHJldGFpbiBvYmplY3Q7IHJldHVybnMgdHJ1ZSBpZiBjaGlsZHJlbiBjb21wbGV0ZWx5IGNvdmVyIHRoZSB0aWxlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENvdmVyaW5nWm9vbVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0YWluXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIG9wZXJhdGlvbiB3YXMgY29tcGxldGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRDaGlsZHJlbjogZnVuY3Rpb24oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IHRydWU7XG4gICAgICAgIHZhciB6ID0gY29vcmQuejtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGNvb3JkLmNoaWxkcmVuKHRoaXMubWF4em9vbSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBjb29yZHNbaV0uaWQ7XG4gICAgICAgICAgICBpZiAodGhpcy5fdGlsZXNbaWRdICYmIHRoaXMuX3RpbGVzW2lkXS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICByZXRhaW5baWRdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29tcGxldGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoeiA8IG1heENvdmVyaW5nWm9vbSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBHbyBmdXJ0aGVyIGRvd24gdGhlIGhpZXJhcmNoeSB0byBmaW5kIG1vcmUgdW5sb2FkZWQgY2hpbGRyZW4uXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3Jkc1tpXSwgbWF4Q292ZXJpbmdab29tLCByZXRhaW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcGxldGU7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBsb2FkZWQgcGFyZW50IG9mIHRoZSBnaXZlbiB0aWxlICh1cCB0byBtaW5Db3ZlcmluZ1pvb20pO1xuICAgICAqIGFkZHMgdGhlIGZvdW5kIHRpbGUgdG8gcmV0YWluIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgdGlsZSBpZiBmb3VuZFxuICAgICAqXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5Db3ZlcmluZ1pvb21cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJldGFpblxuICAgICAqIEByZXR1cm5zIHtUaWxlfSB0aWxlIG9iamVjdFxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRQYXJlbnQ6IGZ1bmN0aW9uKGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbikge1xuICAgICAgICBmb3IgKHZhciB6ID0gY29vcmQueiAtIDE7IHogPj0gbWluQ292ZXJpbmdab29tOyB6LS0pIHtcbiAgICAgICAgICAgIGNvb3JkID0gY29vcmQucGFyZW50KHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2Nvb3JkLmlkXTtcbiAgICAgICAgICAgIGlmICh0aWxlICYmIHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0YWluW2Nvb3JkLmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aWxlcyB0aGF0IGFyZSBvdXRzaWRlIHRoZSB2aWV3cG9ydCBhbmQgYWRkcyBuZXcgdGlsZXMgdGhhdFxuICAgICAqIGFyZSBpbnNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXNlZCwgdHJhbnNmb3JtLCBmYWRlRHVyYXRpb24pIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBjb29yZDtcbiAgICAgICAgdmFyIHRpbGU7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBvdmVyem9vbWluZy91bmRlcnpvb21pbmcgYW1vdW50cy5cbiAgICAgICAgdmFyIHpvb20gPSBNYXRoLmZsb29yKHRoaXMuZ2V0Wm9vbSh0cmFuc2Zvcm0pKTtcbiAgICAgICAgdmFyIG1pbkNvdmVyaW5nWm9vbSA9IHV0aWwuY2xhbXAoem9vbSAtIDEwLCB0aGlzLm1pbnpvb20sIHRoaXMubWF4em9vbSk7XG4gICAgICAgIHZhciBtYXhDb3ZlcmluZ1pvb20gPSB1dGlsLmNsYW1wKHpvb20gKyAxLCAgdGhpcy5taW56b29tLCB0aGlzLm1heHpvb20pO1xuXG4gICAgICAgIC8vIFJldGFpbiBpcyBhIGxpc3Qgb2YgdGlsZXMgdGhhdCB3ZSBzaG91bGRuJ3QgZGVsZXRlLCBldmVuIGlmIHRoZXkgYXJlIG5vdFxuICAgICAgICAvLyB0aGUgbW9zdCBpZGVhbCB0aWxlIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydC4gVGhpcyBtYXkgaW5jbHVkZSB0aWxlcyBsaWtlXG4gICAgICAgIC8vIHBhcmVudCBvciBjaGlsZCB0aWxlcyB0aGF0IGFyZSAqYWxyZWFkeSogbG9hZGVkLlxuICAgICAgICB2YXIgcmV0YWluID0ge307XG4gICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICAvLyBDb3ZlcmVkIGlzIGEgbGlzdCBvZiByZXRhaW5lZCB0aWxlcyB3aG8ncyBhcmVhcyBhcmUgZnVsbCBjb3ZlcmVkIGJ5IG90aGVyLFxuICAgICAgICAvLyBiZXR0ZXIsIHJldGFpbmVkIHRpbGVzLiBUaGV5IGFyZSBub3QgZHJhd24gc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fY292ZXJlZFRpbGVzID0ge307XG5cbiAgICAgICAgdmFyIHJlcXVpcmVkID0gdXNlZCA/IHRoaXMuY292ZXJpbmdUaWxlcyh0cmFuc2Zvcm0pIDogW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXF1aXJlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29vcmQgPSByZXF1aXJlZFtpXTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmFkZFRpbGUoY29vcmQpO1xuXG4gICAgICAgICAgICByZXRhaW5bY29vcmQuaWRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHRpbGUubG9hZGVkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBUaGUgdGlsZSB3ZSByZXF1aXJlIGlzIG5vdCB5ZXQgbG9hZGVkLlxuICAgICAgICAgICAgLy8gUmV0YWluIGNoaWxkIG9yIHBhcmVudCB0aWxlcyB0aGF0IGNvdmVyIHRoZSBzYW1lIGFyZWEuXG4gICAgICAgICAgICBpZiAoIXRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3JkLCBtYXhDb3ZlcmluZ1pvb20sIHJldGFpbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmRMb2FkZWRQYXJlbnQoY29vcmQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHJldGFpbikge1xuICAgICAgICAgICAgY29vcmQgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1tpZF07XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aWxlLnRpbWVBZGRlZCA+IG5vdyAtIChmYWRlRHVyYXRpb24gfHwgMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHRpbGUgaXMgc3RpbGwgZmFkaW5nIGluLiBGaW5kIHRpbGVzIHRvIGNyb3NzLWZhZGUgd2l0aCBpdC5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maW5kTG9hZGVkQ2hpbGRyZW4oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0YWluW2lkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5kTG9hZGVkUGFyZW50KGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0aWxlcyB3ZSBkb24ndCBuZWVkIGFueW1vcmUuXG4gICAgICAgIHZhciByZW1vdmUgPSB1dGlsLmtleXNEaWZmZXJlbmNlKHRoaXMuX3RpbGVzLCByZXRhaW4pO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVRpbGUoK3JlbW92ZVtpXSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgdGlsZSwgZ2l2ZW4gaXRzIGNvb3JkaW5hdGUsIHRvIHRoZSBweXJhbWlkLlxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7Q29vcmRpbmF0ZX0gdGhlIGNvb3JkaW5hdGUuXG4gICAgICovXG4gICAgYWRkVGlsZTogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl90aWxlc1tjb29yZC5pZF07XG4gICAgICAgIGlmICh0aWxlKVxuICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG5cbiAgICAgICAgdmFyIHdyYXBwZWQgPSBjb29yZC53cmFwcGVkKCk7XG4gICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1t3cmFwcGVkLmlkXTtcblxuICAgICAgICBpZiAoIXRpbGUpIHtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl9jYWNoZS5nZXQod3JhcHBlZC5pZCk7XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aGlzLl9yZWRvUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVkb1BsYWNlbWVudCh0aWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGlsZSkge1xuICAgICAgICAgICAgdmFyIHpvb20gPSBjb29yZC56O1xuICAgICAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gem9vbSA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLm1heHpvb20pIDogMTtcbiAgICAgICAgICAgIHRpbGUgPSBuZXcgVGlsZSh3cmFwcGVkLCB0aGlzLnRpbGVTaXplICogb3ZlcnNjYWxpbmcpO1xuICAgICAgICAgICAgdGhpcy5fbG9hZCh0aWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbGUudXNlcysrO1xuICAgICAgICB0aGlzLl90aWxlc1tjb29yZC5pZF0gPSB0aWxlO1xuICAgICAgICB0aGlzLl9hZGQodGlsZSwgY29vcmQpO1xuXG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSB0aWxlLCBnaXZlbiBpdHMgaWQsIGZyb20gdGhlIHB5cmFtaWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIHRpbGUgaWRcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBub3RoaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICByZW1vdmVUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2lkXTtcbiAgICAgICAgaWYgKCF0aWxlKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRpbGUudXNlcy0tO1xuICAgICAgICBkZWxldGUgdGhpcy5fdGlsZXNbaWRdO1xuICAgICAgICB0aGlzLl9yZW1vdmUodGlsZSk7XG5cbiAgICAgICAgaWYgKHRpbGUudXNlcyA+IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZS5hZGQodGlsZS5jb29yZC53cmFwcGVkKCkuaWQsIHRpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fYWJvcnQodGlsZSk7XG4gICAgICAgICAgICB0aGlzLl91bmxvYWQodGlsZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCB0aWxlcyBmcm9tIHRoaXMgcHlyYW1pZFxuICAgICAqL1xuICAgIGNsZWFyVGlsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBpZCBpbiB0aGlzLl90aWxlcylcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlVGlsZShpZCk7XG4gICAgICAgIHRoaXMuX2NhY2hlLnJlc2V0KCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZvciBhIGdpdmVuIGNvb3JkaW5hdGUsIHNlYXJjaCB0aHJvdWdoIG91ciBjdXJyZW50IHRpbGVzIGFuZCBhdHRlbXB0XG4gICAgICogdG8gZmluZCBhIHRpbGUgYXQgdGhhdCBwb2ludFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSB0aWxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aWxlQXQ6IGZ1bmN0aW9uKGNvb3JkKSB7XG4gICAgICAgIHZhciBpZHMgPSB0aGlzLm9yZGVyZWRJRHMoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gdGhpcy5fdGlsZXNbaWRzW2ldXTtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aWxlLnBvc2l0aW9uQXQoY29vcmQsIHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICBpZiAocG9zICYmIHBvcy54ID49IDAgJiYgcG9zLnggPCA0MDk2ICYmIHBvcy55ID49IDAgJiYgcG9zLnkgPCA0MDk2KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGNsaWNrIGlzIHdpdGhpbiB0aGUgdmlld3BvcnQuIFRoZXJlIGlzIG9ubHkgZXZlciBvbmUgdGlsZSBpblxuICAgICAgICAgICAgICAgIC8vIGEgbGF5ZXIgdGhhdCBoYXMgdGhpcyBwcm9wZXJ0eS5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB0aWxlOiB0aWxlLFxuICAgICAgICAgICAgICAgICAgICB4OiBwb3MueCxcbiAgICAgICAgICAgICAgICAgICAgeTogcG9zLnksXG4gICAgICAgICAgICAgICAgICAgIHNjYWxlOiBwb3Muc2NhbGVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlU291cmNlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlU291cmNlKG9wdGlvbnMpIHtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLCB1dGlsLnBpY2sob3B0aW9ucywgWyd1cmwnLCAndGlsZVNpemUnXSkpO1xuXG4gICAgaWYgKHRoaXMudGlsZVNpemUgIT09IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyJyk7XG4gICAgfVxuXG4gICAgU291cmNlLl9sb2FkVGlsZUpTT04uY2FsbCh0aGlzLCBvcHRpb25zKTtcbn1cblxuVmVjdG9yVGlsZVNvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIG1pbnpvb206IDAsXG4gICAgbWF4em9vbTogMjIsXG4gICAgdGlsZVNpemU6IDUxMixcbiAgICByZXBhcnNlT3ZlcnNjYWxlZDogdHJ1ZSxcbiAgICBfbG9hZGVkOiBmYWxzZSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9weXJhbWlkICYmIHRoaXMuX3B5cmFtaWQubG9hZGVkKCk7XG4gICAgfSxcblxuICAgIHVwZGF0ZTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIGlmICh0aGlzLl9weXJhbWlkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVkb1BsYWNlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fcHlyYW1pZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQub3JkZXJlZElEcygpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl9weXJhbWlkLmdldFRpbGUoaWRzW2ldKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcbiAgICBmZWF0dXJlc0F0OiBTb3VyY2UuX3ZlY3RvckZlYXR1cmVzQXQsXG5cbiAgICBfbG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gdGlsZS5jb29yZC56ID4gdGhpcy5tYXh6b29tID8gTWF0aC5wb3coMiwgdGlsZS5jb29yZC56IC0gdGhpcy5tYXh6b29tKSA6IDE7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICB1cmw6IHRpbGUuY29vcmQudXJsKHRoaXMudGlsZXMsIHRoaXMubWF4em9vbSksXG4gICAgICAgICAgICB1aWQ6IHRpbGUudWlkLFxuICAgICAgICAgICAgY29vcmQ6IHRpbGUuY29vcmQsXG4gICAgICAgICAgICB6b29tOiB0aWxlLmNvb3JkLnosXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb20sXG4gICAgICAgICAgICB0aWxlU2l6ZTogdGhpcy50aWxlU2l6ZSAqIG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgc291cmNlOiB0aGlzLmlkLFxuICAgICAgICAgICAgb3ZlcnNjYWxpbmc6IG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgYW5nbGU6IHRoaXMubWFwLnRyYW5zZm9ybS5hbmdsZSxcbiAgICAgICAgICAgIHBpdGNoOiB0aGlzLm1hcC50cmFuc2Zvcm0ucGl0Y2gsXG4gICAgICAgICAgICBjb2xsaXNpb25EZWJ1ZzogdGhpcy5tYXAuY29sbGlzaW9uRGVidWdcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGlsZS53b3JrZXJJRCkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbG9hZCB0aWxlJywgcGFyYW1zLCB0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcywgdGlsZSksIHRpbGUud29ya2VySUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIHRpbGUnLCBwYXJhbXMsIHRoaXMuX3RpbGVMb2FkZWQuYmluZCh0aGlzLCB0aWxlKSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX3RpbGVMb2FkZWQ6IGZ1bmN0aW9uKHRpbGUsIGVyciwgZGF0YSkge1xuICAgICAgICBpZiAodGlsZS5hYm9ydGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5lcnJvcicsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLmxvYWRWZWN0b3JEYXRhKGRhdGEpO1xuXG4gICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgdGlsZS5yZWRvV2hlbkRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdhYm9ydCB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9yZWRvVGlsZVBsYWNlbWVudDogZnVuY3Rpb24odGlsZSkge1xuXG4gICAgICAgIGlmICghdGlsZS5sb2FkZWQgfHwgdGlsZS5yZWRvaW5nUGxhY2VtZW50KSB7XG4gICAgICAgICAgICB0aWxlLnJlZG9XaGVuRG9uZSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdyZWRvIHBsYWNlbWVudCcsIHtcbiAgICAgICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBhbmdsZTogdGhpcy5tYXAudHJhbnNmb3JtLmFuZ2xlLFxuICAgICAgICAgICAgcGl0Y2g6IHRoaXMubWFwLnRyYW5zZm9ybS5waXRjaCxcbiAgICAgICAgICAgIGNvbGxpc2lvbkRlYnVnOiB0aGlzLm1hcC5jb2xsaXNpb25EZWJ1Z1xuICAgICAgICB9LCBkb25lLmJpbmQodGhpcyksIHRpbGUud29ya2VySUQpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGRvbmUoXywgZGF0YSkge1xuICAgICAgICAgICAgdGlsZS5yZWxvYWRTeW1ib2xEYXRhKGRhdGEsIHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuXG4gICAgICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICAgICAgICAgIHRpbGUucmVkb1doZW5Eb25lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuLi9nZW8vY29vcmRpbmF0ZScpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWaWRlb1NvdXJjZTtcblxuLyoqXG4gKiBDcmVhdGUgYSBWaWRlbyBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICogQGNsYXNzIFZpZGVvU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge1N0cmluZ3xBcnJheX0gb3B0aW9ucy51cmwgQSBzdHJpbmcgb3IgYXJyYXkgb2YgVVJMKHMpIHRvIHZpZGVvIGZpbGVzXG4gKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLmNvb3JkaW5hdGVzIGxhdCxsbmcgY29vcmRpbmF0ZXMgaW4gb3JkZXIgY2xvY2t3aXNlIHN0YXJ0aW5nIGF0IHRoZSB0b3AgbGVmdDogdGwsIHRyLCBiciwgYmxcbiAqIEBleGFtcGxlXG4gKiB2YXIgc291cmNlT2JqID0gbmV3IG1hcGJveGdsLlZpZGVvU291cmNlKHtcbiAqICAgIHVybDogW1xuICogICAgICAgICdodHRwczovL3d3dy5tYXBib3guY29tL3ZpZGVvcy9iYWx0aW1vcmUtc21va2UubXA0JyxcbiAqICAgICAgICAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS92aWRlb3MvYmFsdGltb3JlLXNtb2tlLndlYm0nXG4gKiAgICBdLFxuICogICAgY29vcmRpbmF0ZXM6IFtcbiAqICAgICAgICBbMzkuMTg1Nzk5MDcyMjk3NDgsIC03Ni41NDMzNTczNzIyODM5NF0sXG4gKiAgICAgICAgWzM5LjE4MzgzNjQ4NDc1ODcsIC03Ni41MjgwMzY1OTQzOTA4N10sXG4gKiAgICAgICAgWzM5LjE3NjgzMzkyNTA3NjA2LCAtNzYuNTI5NTM4NjMxNDM5Ml0sXG4gKiAgICAgICAgWzM5LjE3ODc2MzQ0MTA2NjQyLCAtNzYuNTQ1MjAyNzMyMDg2MThdXG4gKiAgICBdXG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBWaWRlb1NvdXJjZShvcHRpb25zKSB7XG4gICAgdGhpcy5jb29yZGluYXRlcyA9IG9wdGlvbnMuY29vcmRpbmF0ZXM7XG5cbiAgICBhamF4LmdldFZpZGVvKG9wdGlvbnMudXJsLCBmdW5jdGlvbihlcnIsIHZpZGVvKSB7XG4gICAgICAgIC8vIEBUT0RPIGhhbmRsZSBlcnJvcnMgdmlhIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy52aWRlbyA9IHZpZGVvO1xuICAgICAgICB0aGlzLnZpZGVvLmxvb3AgPSB0cnVlO1xuXG4gICAgICAgIHZhciBsb29wSUQ7XG5cbiAgICAgICAgLy8gc3RhcnQgcmVwYWludGluZyB3aGVuIHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gICAgICAgIHRoaXMudmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheWluZycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbG9vcElEID0gdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoSW5maW5pdHkpO1xuICAgICAgICAgICAgdGhpcy5tYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gc3RvcCByZXBhaW50aW5nIHdoZW4gdmlkZW8gc3RvcHNcbiAgICAgICAgdGhpcy52aWRlby5hZGRFdmVudExpc3RlbmVyKCdwYXVzZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5jYW5jZWwobG9vcElEKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcCkge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJyk7XG4gICAgICAgIH1cbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgSFRNTCB2aWRlbyBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRWaWRlbzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvO1xuICAgIH0sXG5cbiAgICBvbkFkZDogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMubWFwID0gbWFwO1xuICAgICAgICBpZiAodGhpcy52aWRlbykge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogQ2FsY3VsYXRlIHdoaWNoIG1lcmNhdG9yIHRpbGUgaXMgc3VpdGFibGUgZm9yIHJlbmRlcmluZyB0aGUgdmlkZW8gaW5cbiAgICAgICAgICogYW5kIGNyZWF0ZSBhIGJ1ZmZlciB3aXRoIHRoZSBjb3JuZXIgY29vcmRpbmF0ZXMuIFRoZXNlIGNvb3JkaW5hdGVzXG4gICAgICAgICAqIG1heSBiZSBvdXRzaWRlIHRoZSB0aWxlLCBiZWNhdXNlIHJhc3RlciB0aWxlcyBhcmVuJ3QgY2xpcHBlZCB3aGVuIHJlbmRlcmluZy5cbiAgICAgICAgICovXG4gICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcbiAgICAgICAgdmFyIGNvb3JkcyA9IHRoaXMuY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uKGxhdGxuZykge1xuICAgICAgICAgICAgdmFyIGxvYyA9IExhdExuZy5jb252ZXJ0KGxhdGxuZyk7XG4gICAgICAgICAgICByZXR1cm4gbWFwLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUobG9jKS56b29tVG8oMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtaW5YID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtaW5ZID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtYXhYID0gLUluZmluaXR5O1xuICAgICAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGR4ID0gbWF4WCAtIG1pblg7XG4gICAgICAgIHZhciBkeSA9IG1heFkgLSBtaW5ZO1xuICAgICAgICB2YXIgZE1heCA9IE1hdGgubWF4KGR4LCBkeSk7XG4gICAgICAgIHZhciBjZW50ZXIgPSBuZXcgQ29vcmRpbmF0ZSgobWluWCArIG1heFgpIC8gMiwgKG1pblkgKyBtYXhZKSAvIDIsIDApXG4gICAgICAgICAgICAuem9vbVRvKE1hdGguZmxvb3IoLU1hdGgubG9nKGRNYXgpIC8gTWF0aC5MTjIpKTtcblxuICAgICAgICB2YXIgdGlsZUV4dGVudCA9IDQwOTY7XG4gICAgICAgIHZhciB0aWxlQ29vcmRzID0gY29vcmRzLm1hcChmdW5jdGlvbihjb29yZCkge1xuICAgICAgICAgICAgdmFyIHpvb21lZENvb3JkID0gY29vcmQuem9vbVRvKGNlbnRlci56b29tKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZCgoem9vbWVkQ29vcmQuY29sdW1uIC0gY2VudGVyLmNvbHVtbikgKiB0aWxlRXh0ZW50KSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKCh6b29tZWRDb29yZC5yb3cgLSBjZW50ZXIucm93KSAqIHRpbGVFeHRlbnQpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGdsID0gbWFwLnBhaW50ZXIuZ2w7XG4gICAgICAgIHZhciBtYXhJbnQxNiA9IDMyNzY3O1xuICAgICAgICB2YXIgYXJyYXkgPSBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICB0aWxlQ29vcmRzWzBdLngsIHRpbGVDb29yZHNbMF0ueSwgMCwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMV0ueCwgdGlsZUNvb3Jkc1sxXS55LCBtYXhJbnQxNiwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbM10ueCwgdGlsZUNvb3Jkc1szXS55LCAwLCBtYXhJbnQxNixcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMl0ueCwgdGlsZUNvb3Jkc1syXS55LCBtYXhJbnQxNiwgbWF4SW50MTZcbiAgICAgICAgXSk7XG5cbiAgICAgICAgdGhpcy50aWxlID0gbmV3IFRpbGUoKTtcbiAgICAgICAgdGhpcy50aWxlLmJ1Y2tldHMgPSB7fTtcblxuICAgICAgICB0aGlzLnRpbGUuYm91bmRzQnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGUuYm91bmRzQnVmZmVyKTtcbiAgICAgICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGFycmF5LCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgdGhpcy5jZW50ZXIgPSBjZW50ZXI7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvICYmIHRoaXMudmlkZW8ucmVhZHlTdGF0ZSA+PSAyO1xuICAgIH0sXG5cbiAgICB1cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBub29wXG4gICAgfSxcblxuICAgIHJlbmRlcjogZnVuY3Rpb24obGF5ZXJzLCBwYWludGVyKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnZpZGVvLnJlYWR5U3RhdGUgPCAyKSByZXR1cm47IC8vIG5vdCBlbm91Z2ggZGF0YSBmb3IgY3VycmVudCBwb3NpdGlvblxuXG4gICAgICAgIHZhciBjID0gdGhpcy5jZW50ZXI7XG4gICAgICAgIHRoaXMudGlsZS5jYWxjdWxhdGVNYXRyaWNlcyhjLnpvb20sIGMuY29sdW1uLCBjLnJvdywgdGhpcy5tYXAudHJhbnNmb3JtLCBwYWludGVyKTtcblxuICAgICAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuICAgICAgICBpZiAoIXRoaXMudGlsZS50ZXh0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLnRpbGUudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLnZpZGVvKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy52aWRlbyk7XG4gICAgICAgIH1cblxuICAgICAgICBwYWludGVyLmRyYXdMYXllcnMobGF5ZXJzLCB0aGlzLnRpbGUucG9zTWF0cml4LCB0aGlzLnRpbGUpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihwb2ludCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQWN0b3IgPSByZXF1aXJlKCcuLi91dGlsL2FjdG9yJyk7XG52YXIgV29ya2VyVGlsZSA9IHJlcXVpcmUoJy4vd29ya2VyX3RpbGUnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIHZ0ID0gcmVxdWlyZSgndmVjdG9yLXRpbGUnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG52YXIgZ2VvanNvbnZ0ID0gcmVxdWlyZSgnZ2VvanNvbi12dCcpO1xudmFyIEdlb0pTT05XcmFwcGVyID0gcmVxdWlyZSgnLi9nZW9qc29uX3dyYXBwZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWxmKSB7XG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoc2VsZik7XG59O1xuXG5mdW5jdGlvbiBXb3JrZXIoc2VsZikge1xuICAgIHRoaXMuc2VsZiA9IHNlbGY7XG4gICAgdGhpcy5hY3RvciA9IG5ldyBBY3RvcihzZWxmLCB0aGlzKTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcblxuICAgIHRoaXMubG9hZGVkID0ge307XG4gICAgdGhpcy5sYXllcnMgPSBbXTtcbiAgICB0aGlzLmdlb0pTT05JbmRleGVzID0ge307XG59XG5cbnV0aWwuZXh0ZW5kKFdvcmtlci5wcm90b3R5cGUsIHtcbiAgICAnc2V0IGxheWVycyc6IGZ1bmN0aW9uKGxheWVycykge1xuICAgICAgICB0aGlzLmxheWVycyA9IGxheWVycztcbiAgICB9LFxuXG4gICAgJ2xvYWQgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHBhcmFtcy5zb3VyY2UsXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmICghdGhpcy5sb2FkaW5nW3NvdXJjZV0pXG4gICAgICAgICAgICB0aGlzLmxvYWRpbmdbc291cmNlXSA9IHt9O1xuXG5cbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLmxvYWRpbmdbc291cmNlXVt1aWRdID0gbmV3IFdvcmtlclRpbGUocGFyYW1zKTtcblxuICAgICAgICB0aWxlLnhociA9IGFqYXguZ2V0QXJyYXlCdWZmZXIocGFyYW1zLnVybCwgZG9uZS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBmdW5jdGlvbiBkb25lKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9hZGluZ1tzb3VyY2VdW3VpZF07XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgICAgICB0aWxlLmRhdGEgPSBuZXcgdnQuVmVjdG9yVGlsZShuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIHRpbGUucGFyc2UodGlsZS5kYXRhLCB0aGlzLmxheWVycywgdGhpcy5hY3RvciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRlZFtzb3VyY2VdID0gdGhpcy5sb2FkZWRbc291cmNlXSB8fCB7fTtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bdWlkXSA9IHRpbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbG9hZCB0aWxlJzogZnVuY3Rpb24ocGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgbG9hZGVkID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGVkICYmIGxvYWRlZFt1aWRdKSB7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IGxvYWRlZFt1aWRdO1xuICAgICAgICAgICAgdGlsZS5wYXJzZSh0aWxlLmRhdGEsIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2Fib3J0IHRpbGUnOiBmdW5jdGlvbihwYXJhbXMpIHtcbiAgICAgICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGluZyAmJiBsb2FkaW5nW3VpZF0pIHtcbiAgICAgICAgICAgIGxvYWRpbmdbdWlkXS54aHIuYWJvcnQoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkaW5nW3VpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbW92ZSB0aWxlJzogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIHVpZCA9IHBhcmFtcy51aWQ7XG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkZWRbdWlkXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAncmVkbyBwbGFjZW1lbnQnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gbG9hZGVkW3VpZF07XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGlsZS5yZWRvUGxhY2VtZW50KHBhcmFtcy5hbmdsZSwgcGFyYW1zLnBpdGNoLCBwYXJhbXMuY29sbGlzaW9uRGVidWcpO1xuXG4gICAgICAgICAgICBpZiAocmVzdWx0LnJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdC5yZXN1bHQsIHJlc3VsdC50cmFuc2ZlcmFibGVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2UgaWYgKGxvYWRpbmcgJiYgbG9hZGluZ1t1aWRdKSB7XG4gICAgICAgICAgICBsb2FkaW5nW3VpZF0uYW5nbGUgPSBwYXJhbXMuYW5nbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3BhcnNlIGdlb2pzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBpbmRleERhdGEgPSBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgdGhpcy5nZW9KU09OSW5kZXhlc1twYXJhbXMuc291cmNlXSA9IGdlb2pzb252dChkYXRhLCB7YmFzZVpvb206IHBhcmFtcy5tYXhab29tfSk7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIC8vIFRPRE8gYWNjZXB0IHBhcmFtcy51cmwgZm9yIHVybHMgaW5zdGVhZFxuXG4gICAgICAgIC8vIE5vdCwgYmVjYXVzZSBvZiBzYW1lIG9yaWdpbiBpc3N1ZXMsIHVybHMgbXVzdCBlaXRoZXIgaW5jbHVkZSBhblxuICAgICAgICAvLyBleHBsaWNpdCBvcmlnaW4gb3IgYWJzb2x1dGUgcGF0aC5cbiAgICAgICAgLy8gaWU6IC9mb28vYmFyLmpzb24gb3IgaHR0cDovL2V4YW1wbGUuY29tL2Jhci5qc29uXG4gICAgICAgIC8vIGJ1dCBub3QgLi4vZm9vL2Jhci5qc29uXG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zLmRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBhamF4LmdldEpTT04ocGFyYW1zLmRhdGEsIGluZGV4RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpbmRleERhdGEobnVsbCwgcGFyYW1zLmRhdGEpO1xuICAgIH0sXG5cbiAgICAnbG9hZCBnZW9qc29uIHRpbGUnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwYXJhbXMuc291cmNlLFxuICAgICAgICAgICAgY29vcmQgPSBwYXJhbXMuY29vcmQ7XG5cbiAgICAgICAgLy8gY29uc29sZS50aW1lKCd0aWxlICcgKyBjb29yZC56ICsgJyAnICsgY29vcmQueCArICcgJyArIGNvb3JkLnkpO1xuXG4gICAgICAgIHZhciBnZW9KU09OVGlsZSA9IHRoaXMuZ2VvSlNPTkluZGV4ZXNbc291cmNlXS5nZXRUaWxlKGNvb3JkLnosIGNvb3JkLngsIGNvb3JkLnkpO1xuXG4gICAgICAgIC8vIGNvbnNvbGUudGltZUVuZCgndGlsZSAnICsgY29vcmQueiArICcgJyArIGNvb3JkLnggKyAnICcgKyBjb29yZC55KTtcblxuICAgICAgICAvLyBpZiAoIWdlb0pTT05UaWxlKSBjb25zb2xlLmxvZygnbm90IGZvdW5kJywgdGhpcy5nZW9KU09OSW5kZXhlc1tzb3VyY2VdLCBjb29yZCk7XG5cbiAgICAgICAgaWYgKCFnZW9KU09OVGlsZSkgcmV0dXJuIGNhbGxiYWNrKG51bGwsIG51bGwpOyAvLyBub3RoaW5nIGluIHRoZSBnaXZlbiB0aWxlXG5cbiAgICAgICAgdmFyIHRpbGUgPSBuZXcgV29ya2VyVGlsZShwYXJhbXMpO1xuICAgICAgICB0aWxlLnBhcnNlKG5ldyBHZW9KU09OV3JhcHBlcihnZW9KU09OVGlsZS5mZWF0dXJlcyksIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG5cbiAgICAgICAgdGhpcy5sb2FkZWRbc291cmNlXSA9IHRoaXMubG9hZGVkW3NvdXJjZV0gfHwge307XG4gICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bcGFyYW1zLnVpZF0gPSB0aWxlO1xuICAgIH0sXG5cbiAgICAncXVlcnkgZmVhdHVyZXMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB0aWxlID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0gJiYgdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV1bcGFyYW1zLnVpZF07XG4gICAgICAgIGlmICh0aWxlKSB7XG4gICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLnF1ZXJ5KHBhcmFtcywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgW10pO1xuICAgICAgICB9XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBGZWF0dXJlVHJlZSA9IHJlcXVpcmUoJy4uL2RhdGEvZmVhdHVyZV90cmVlJyk7XG52YXIgQ29sbGlzaW9uID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl90aWxlJyk7XG52YXIgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyX3NldCcpO1xudmFyIGNyZWF0ZUJ1Y2tldCA9IHJlcXVpcmUoJy4uL2RhdGEvY3JlYXRlX2J1Y2tldCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlclRpbGU7XG5cbmZ1bmN0aW9uIFdvcmtlclRpbGUocGFyYW1zKSB7XG4gICAgdGhpcy5jb29yZCA9IHBhcmFtcy5jb29yZDtcbiAgICB0aGlzLnVpZCA9IHBhcmFtcy51aWQ7XG4gICAgdGhpcy56b29tID0gcGFyYW1zLnpvb207XG4gICAgdGhpcy5tYXhab29tID0gcGFyYW1zLm1heFpvb207XG4gICAgdGhpcy50aWxlU2l6ZSA9IHBhcmFtcy50aWxlU2l6ZTtcbiAgICB0aGlzLnNvdXJjZSA9IHBhcmFtcy5zb3VyY2U7XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IHBhcmFtcy5vdmVyc2NhbGluZztcbiAgICB0aGlzLmFuZ2xlID0gcGFyYW1zLmFuZ2xlO1xuICAgIHRoaXMucGl0Y2ggPSBwYXJhbXMucGl0Y2g7XG4gICAgdGhpcy5jb2xsaXNpb25EZWJ1ZyA9IHBhcmFtcy5jb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3RhY2tzID0ge307XG59XG5cbldvcmtlclRpbGUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oZGF0YSwgbGF5ZXJzLCBhY3RvciwgY2FsbGJhY2spIHtcblxuICAgIHRoaXMuc3RhdHVzID0gJ3BhcnNpbmcnO1xuXG4gICAgdGhpcy5mZWF0dXJlVHJlZSA9IG5ldyBGZWF0dXJlVHJlZSh0aGlzLmNvb3JkLCB0aGlzLm92ZXJzY2FsaW5nKTtcblxuICAgIHZhciBpLCBrLFxuICAgICAgICB0aWxlID0gdGhpcyxcbiAgICAgICAgbGF5ZXIsXG4gICAgICAgIGJ1Y2tldCxcbiAgICAgICAgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoKSxcbiAgICAgICAgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb24gPSBuZXcgQ29sbGlzaW9uKHRoaXMuem9vbSwgNDA5NiwgdGhpcy50aWxlU2l6ZSksXG4gICAgICAgIGJ1Y2tldHMgPSB7fSxcbiAgICAgICAgYnVja2V0c0luT3JkZXIgPSB0aGlzLmJ1Y2tldHNJbk9yZGVyID0gW10sXG4gICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyID0ge307XG5cbiAgICBjb2xsaXNpb24ucmVzZXQodGhpcy5hbmdsZSwgdGhpcy5waXRjaCk7XG5cbiAgICAvLyBNYXAgbm9uLXJlZiBsYXllcnMgdG8gYnVja2V0cy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKGxheWVyLnJlZilcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBtaW56b29tID0gbGF5ZXIubWluem9vbTtcbiAgICAgICAgaWYgKG1pbnpvb20gJiYgdGhpcy56b29tIDwgbWluem9vbSAmJiBtaW56b29tIDwgdGhpcy5tYXhab29tKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIG1heHpvb20gPSBsYXllci5tYXh6b29tO1xuICAgICAgICBpZiAobWF4em9vbSAmJiB0aGlzLnpvb20gPj0gbWF4em9vbSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2aXNpYmlsaXR5ID0gbGF5ZXIubGF5b3V0LnZpc2liaWxpdHk7XG4gICAgICAgIGlmICh2aXNpYmlsaXR5ID09PSAnbm9uZScpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgdGhpcy56b29tLCB0aGlzLm92ZXJzY2FsaW5nLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbiAgICAgICAgYnVja2V0LmxheWVycyA9IFtsYXllci5pZF07XG5cbiAgICAgICAgYnVja2V0c1tidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICBidWNrZXRzSW5PcmRlci5wdXNoKGJ1Y2tldCk7XG5cbiAgICAgICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgICAgICB2YXIgc291cmNlTGF5ZXIgPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXSlcbiAgICAgICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltzb3VyY2VMYXllcl0gPSB7fTtcbiAgICAgICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXVtidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZ2VvanNvbiB0aWxlXG4gICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5kZXggcmVmIGxheWVycy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKCFsYXllci5yZWYpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBidWNrZXRzW2xheWVyLnJlZl07XG4gICAgICAgIGlmICghYnVja2V0KVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgYnVja2V0LmxheWVycy5wdXNoKGxheWVyLmlkKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0ZW50ID0gNDA5NjtcblxuICAgIC8vIHJlYWQgZWFjaCBsYXllciwgYW5kIHNvcnQgaXRzIGZlYXR1cmVzIGludG8gYnVja2V0c1xuICAgIGlmIChkYXRhLmxheWVycykge1xuICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgIGZvciAoayBpbiBidWNrZXRzQnlTb3VyY2VMYXllcikge1xuICAgICAgICAgICAgbGF5ZXIgPSBkYXRhLmxheWVyc1trXTtcbiAgICAgICAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGxheWVyLmV4dGVudCkgZXh0ZW50ID0gbGF5ZXIuZXh0ZW50O1xuICAgICAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMobGF5ZXIsIGJ1Y2tldHNCeVNvdXJjZUxheWVyW2tdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdlb2pzb25cbiAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMoZGF0YSwgYnVja2V0c0J5U291cmNlTGF5ZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNvcnRMYXllckludG9CdWNrZXRzKGxheWVyLCBidWNrZXRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBmZWF0dXJlID0gbGF5ZXIuZmVhdHVyZShpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBidWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0LmZpbHRlcihmZWF0dXJlKSkge1xuICAgICAgICAgICAgICAgICAgICBidWNrZXQuZmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcHJldlBsYWNlbWVudEJ1Y2tldDtcbiAgICB2YXIgcmVtYWluaW5nID0gYnVja2V0c0luT3JkZXIubGVuZ3RoO1xuXG4gICAgLypcbiAgICAgKiAgVGhlIGFzeW5jIHBhcnNpbmcgaGVyZSBpcyBhIGJpdCB0cmlja3kuXG4gICAgICogIFNvbWUgYnVja2V0cyBkZXBlbmQgb24gcmVzb3VyY2VzIHRoYXQgbWF5IG5lZWQgdG8gYmUgbG9hZGVkIGFzeW5jIChnbHlwaHMpLlxuICAgICAqICBTb21lIGJ1Y2tldHMgbmVlZCB0byBiZSBwYXJzZWQgaW4gb3JkZXIgKHRvIGdldCBjb2xsaXNpb24gcHJpb3JpdGllcyByaWdodCkuXG4gICAgICpcbiAgICAgKiAgRGVwZW5kZW5jaWVzIGNhbGxzIGFyZSBpbml0aWF0ZWQgZmlyc3QgdG8gZ2V0IHRob3NlIHJvbGxpbmcuXG4gICAgICogIEJ1Y2tldHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlciwgYXJlbid0IHRvIHNhdmUgdGltZS5cbiAgICAgKi9cblxuICAgIGZvciAoaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWNrZXQgPSBidWNrZXRzSW5PcmRlcltpXTtcblxuICAgICAgICAvLyBMaW5rIGJ1Y2tldHMgdGhhdCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlclxuICAgICAgICBpZiAoYnVja2V0LmNvbGxpc2lvbikge1xuICAgICAgICAgICAgaWYgKHByZXZQbGFjZW1lbnRCdWNrZXQpIHtcbiAgICAgICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0Lm5leHQgPSBidWNrZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Y2tldC5wcmV2aW91c1BsYWNlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0ID0gYnVja2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5nZXREZXBlbmRlbmNpZXModGhpcywgYWN0b3IsIGRlcGVuZGVuY2llc0RvbmUoYnVja2V0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbW1lZGlhdGVseSBwYXJzZSBidWNrZXRzIHdoZXJlIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGFuZCBubyBkZXBlbmRlbmNpZXNcbiAgICAgICAgaWYgKCFidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQuZ2V0RGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVwZW5kZW5jaWVzRG9uZShidWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgYnVja2V0LmRlcGVuZGVuY2llc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQsIGVycik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VCdWNrZXQodGlsZSwgYnVja2V0LCBza2lwKSB7XG4gICAgICAgIGlmIChidWNrZXQuZ2V0RGVwZW5kZW5jaWVzICYmICFidWNrZXQuZGVwZW5kZW5jaWVzTG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmIChidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQucHJldmlvdXNQbGFjZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoIXNraXApIHtcbiAgICAgICAgICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5mZWF0dXJlcy5sZW5ndGgpIGJ1Y2tldC5hZGRGZWF0dXJlcygpO1xuICAgICAgICAgICAgdmFyIHRpbWUgPSBEYXRlLm5vdygpIC0gbm93O1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0LmZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmZWF0dXJlID0gYnVja2V0LmZlYXR1cmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLmluc2VydChmZWF0dXJlLmJib3goKSwgYnVja2V0LmxheWVycywgZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMgPSBzZWxmLmJ1Y2tldFN0YXRzIHx8IHtfdG90YWw6IDB9O1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMuX3RvdGFsICs9IHRpbWU7XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0c1tidWNrZXQuaWRdID0gKHNlbGYuYnVja2V0U3RhdHNbYnVja2V0LmlkXSB8fCAwKSArIHRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZW1haW5pbmctLTtcblxuICAgICAgICBpZiAoIXJlbWFpbmluZykge1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJ5IHBhcnNpbmcgdGhlIG5leHQgYnVja2V0LCBpZiBpdCBpcyByZWFkeVxuICAgICAgICBpZiAoYnVja2V0Lm5leHQpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5uZXh0LnByZXZpb3VzUGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldC5uZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbmUoKSB7XG5cbiAgICAgICAgdGlsZS5zdGF0dXMgPSAnZG9uZSc7XG5cbiAgICAgICAgaWYgKHRpbGUucmVkb1BsYWNlbWVudEFmdGVyRG9uZSkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRpbGUucmVkb1BsYWNlbWVudCh0aWxlLmFuZ2xlLCB0aWxlLnBpdGNoKS5yZXN1bHQ7XG4gICAgICAgICAgICBidWZmZXJzLmdseXBoVmVydGV4ID0gcmVzdWx0LmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgICAgICBidWZmZXJzLmljb25WZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5pY29uVmVydGV4O1xuICAgICAgICAgICAgYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhbnNmZXJhYmxlcyA9IFtdLFxuICAgICAgICAgICAgZWxlbWVudEdyb3VwcyA9IHt9O1xuXG4gICAgICAgIGZvciAoayBpbiBidWZmZXJzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlcmFibGVzLnB1c2goYnVmZmVyc1trXS5hcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGsgaW4gYnVja2V0cykge1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1trXSA9IGJ1Y2tldHNba10uZWxlbWVudEdyb3VwcztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cHM6IGVsZW1lbnRHcm91cHMsXG4gICAgICAgICAgICBidWZmZXJzOiBidWZmZXJzLFxuICAgICAgICAgICAgZXh0ZW50OiBleHRlbnRcbiAgICAgICAgfSwgdHJhbnNmZXJhYmxlcyk7XG4gICAgfVxufTtcblxuV29ya2VyVGlsZS5wcm90b3R5cGUucmVkb1BsYWNlbWVudCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCwgY29sbGlzaW9uRGVidWcpIHtcblxuICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gJ2RvbmUnKSB7XG4gICAgICAgIHRoaXMucmVkb1BsYWNlbWVudEFmdGVyRG9uZSA9IHRydWU7XG4gICAgICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHZhciBidWZmZXJzID0gbmV3IEJ1ZmZlclNldCgpO1xuICAgIHZhciB0cmFuc2ZlcmFibGVzID0gW107XG4gICAgdmFyIGVsZW1lbnRHcm91cHMgPSB7fTtcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICBjb2xsaXNpb24ucmVzZXQoYW5nbGUsIHBpdGNoKTtcblxuICAgIHZhciBidWNrZXRzSW5PcmRlciA9IHRoaXMuYnVja2V0c0luT3JkZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYnVja2V0ID0gYnVja2V0c0luT3JkZXJbaV07XG5cbiAgICAgICAgaWYgKGJ1Y2tldC50eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgYnVja2V0LnBsYWNlRmVhdHVyZXMoYnVmZmVycywgY29sbGlzaW9uRGVidWcpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1tidWNrZXQuaWRdID0gYnVja2V0LmVsZW1lbnRHcm91cHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBrIGluIGJ1ZmZlcnMpIHtcbiAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGJ1ZmZlcnNba10uYXJyYXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHJlc3VsdDoge1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwczogZWxlbWVudEdyb3VwcyxcbiAgICAgICAgICAgIGJ1ZmZlcnM6IGJ1ZmZlcnNcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmZXJhYmxlczogdHJhbnNmZXJhYmxlc1xuICAgIH07XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQW5pbWF0aW9uTG9vcDtcblxuZnVuY3Rpb24gQW5pbWF0aW9uTG9vcCgpIHtcbiAgICB0aGlzLm4gPSAwO1xuICAgIHRoaXMudGltZXMgPSBbXTtcbn1cblxuLy8gQXJlIGFsbCBhbmltYXRpb25zIGRvbmU/XG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5zdG9wcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQudGltZSA+PSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgIH0pO1xuICAgIHJldHVybiAhdGhpcy50aW1lcy5sZW5ndGg7XG59O1xuXG4vLyBBZGQgYSBuZXcgYW5pbWF0aW9uIHRoYXQgd2lsbCBydW4gdCBtaWxsaXNlY29uZHNcbi8vIFJldHVybnMgYW4gaWQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgaXQgbGF5ZXJcbkFuaW1hdGlvbkxvb3AucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aGlzLnRpbWVzLnB1c2goeyBpZDogdGhpcy5uLCB0aW1lOiB0ICsgKG5ldyBEYXRlKCkpLmdldFRpbWUoKSB9KTtcbiAgICByZXR1cm4gdGhpcy5uKys7XG59O1xuXG4vLyBDYW5jZWwgYW4gYW5pbWF0aW9uXG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbihuKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQuaWQgIT09IG47XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSW1hZ2VTcHJpdGU7XG5cbmZ1bmN0aW9uIEltYWdlU3ByaXRlKGJhc2UpIHtcbiAgICB0aGlzLmJhc2UgPSBiYXNlO1xuICAgIHRoaXMucmV0aW5hID0gYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMTtcblxuICAgIGJhc2UgPSB0aGlzLmJhc2UgKyAodGhpcy5yZXRpbmEgPyAnQDJ4JyA6ICcnKTtcblxuICAgIGFqYXguZ2V0SlNPTihiYXNlICsgJy5qc29uJywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgaWYgKHRoaXMuaW1nKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgYWpheC5nZXRJbWFnZShiYXNlICsgJy5wbmcnLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByZW11bHRpcGx5IHRoZSBzcHJpdGVcbiAgICAgICAgdmFyIGRhdGEgPSBpbWcuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgbmV3ZGF0YSA9IGltZy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgICAgICAgIHZhciBhbHBoYSA9IGRhdGFbaSArIDNdIC8gMjU1O1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMF0gPSBkYXRhW2kgKyAwXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMV0gPSBkYXRhW2kgKyAxXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMl0gPSBkYXRhW2kgKyAyXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgM10gPSBkYXRhW2kgKyAzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW1nID0gaW1nO1xuICAgICAgICBpZiAodGhpcy5kYXRhKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5sb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gISEodGhpcy5kYXRhICYmIHRoaXMuaW1nKTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbigvKmdsKi8pIHtcbiAgICBpZiAoYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMSAhPT0gdGhpcy5yZXRpbmEpIHtcbiAgICAgICAgdmFyIG5ld1Nwcml0ZSA9IG5ldyBJbWFnZVNwcml0ZSh0aGlzLmJhc2UpO1xuICAgICAgICBuZXdTcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuaW1nID0gbmV3U3ByaXRlLmltZztcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ld1Nwcml0ZS5kYXRhO1xuICAgICAgICAgICAgdGhpcy5yZXRpbmEgPSBuZXdTcHJpdGUucmV0aW5hO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIFNwcml0ZVBvc2l0aW9uKCkge31cblNwcml0ZVBvc2l0aW9uLnByb3RvdHlwZSA9IHsgeDogMCwgeTogMCwgd2lkdGg6IDAsIGhlaWdodDogMCwgcGl4ZWxSYXRpbzogMSwgc2RmOiBmYWxzZSB9O1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUuZ2V0U3ByaXRlUG9zaXRpb24gPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCgpKSByZXR1cm4gbmV3IFNwcml0ZVBvc2l0aW9uKCk7XG5cbiAgICB2YXIgcG9zID0gdGhpcy5kYXRhICYmIHRoaXMuZGF0YVtuYW1lXTtcbiAgICBpZiAocG9zICYmIHRoaXMuaW1nKSByZXR1cm4gcG9zO1xuXG4gICAgcmV0dXJuIG5ldyBTcHJpdGVQb3NpdGlvbigpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge307XG5cbnJlZmVyZW5jZS5sYXlvdXQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BzKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIHRoaXNbcF0gPSBwcm9wc1twXTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHByb3AgaW4gcHJvcGVydGllcykge1xuICAgICAgICBpZiAocHJvcGVydGllc1twcm9wXS5kZWZhdWx0ID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBQcm9wZXJ0aWVzLnByb3RvdHlwZVtwcm9wXSA9IHByb3BlcnRpZXNbcHJvcF0uZGVmYXVsdDtcbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHNbY2xhc3NOYW1lLnJlcGxhY2UoJ2xheW91dF8nLCAnJyldID0gUHJvcGVydGllcztcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi9yZWZlcmVuY2UnKTtcbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5yZWZlcmVuY2UucGFpbnQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgQ2FsY3VsYXRlZCA9IGZ1bmN0aW9uKCkge307XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcykge1xuICAgICAgICB2YXIgcHJvcCA9IHByb3BlcnRpZXNbcF0sXG4gICAgICAgICAgICB2YWx1ZSA9IHByb3AuZGVmYXVsdDtcblxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgICAgIGlmIChwcm9wLnR5cGUgPT09ICdjb2xvcicpIHZhbHVlID0gcGFyc2VDU1NDb2xvcih2YWx1ZSk7XG5cbiAgICAgICAgQ2FsY3VsYXRlZC5wcm90b3R5cGVbcF0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBDYWxjdWxhdGVkLnByb3RvdHlwZS5oaWRkZW4gPSBmYWxzZTtcbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgncGFpbnRfJywgJycpXSA9IENhbGN1bGF0ZWQ7XG59KTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4uL3NvdXJjZS9zb3VyY2UnKTtcbnZhciBTdHlsZUxheWVyID0gcmVxdWlyZSgnLi9zdHlsZV9sYXllcicpO1xudmFyIEltYWdlU3ByaXRlID0gcmVxdWlyZSgnLi9pbWFnZV9zcHJpdGUnKTtcbnZhciBHbHlwaFNvdXJjZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nbHlwaF9zb3VyY2UnKTtcbnZhciBHbHlwaEF0bGFzID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoX2F0bGFzJyk7XG52YXIgU3ByaXRlQXRsYXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvc3ByaXRlX2F0bGFzJyk7XG52YXIgTGluZUF0bGFzID0gcmVxdWlyZSgnLi4vcmVuZGVyL2xpbmVfYXRsYXMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplU3R5bGVVUkw7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi91dGlsL2Rpc3BhdGNoZXInKTtcbnZhciBBbmltYXRpb25Mb29wID0gcmVxdWlyZSgnLi9hbmltYXRpb25fbG9vcCcpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvbGliL3ZhbGlkYXRlL2xhdGVzdCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlO1xuXG5mdW5jdGlvbiBTdHlsZShzdHlsZXNoZWV0LCBhbmltYXRpb25Mb29wKSB7XG4gICAgdGhpcy5hbmltYXRpb25Mb29wID0gYW5pbWF0aW9uTG9vcCB8fCBuZXcgQW5pbWF0aW9uTG9vcCgpO1xuICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKE1hdGgubWF4KGJyb3dzZXIuaGFyZHdhcmVDb25jdXJyZW5jeSAtIDEsIDEpLCB0aGlzKTtcbiAgICB0aGlzLmdseXBoQXRsYXMgPSBuZXcgR2x5cGhBdGxhcygxMDI0LCAxMDI0KTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzID0gbmV3IFNwcml0ZUF0bGFzKDUxMiwgNTEyKTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzLnJlc2l6ZShicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIHRoaXMubGluZUF0bGFzID0gbmV3IExpbmVBdGxhcygyNTYsIDUxMik7XG5cbiAgICB0aGlzLl9sYXllcnMgPSB7fTtcbiAgICB0aGlzLl9vcmRlciAgPSBbXTtcbiAgICB0aGlzLl9ncm91cHMgPSBbXTtcbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcblxuICAgIHRoaXMuem9vbUhpc3RvcnkgPSB7fTtcblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFNvdXJjZUV2ZW50JyxcbiAgICAgICAgJ19mb3J3YXJkVGlsZUV2ZW50JyxcbiAgICAgICAgJ19yZWRvUGxhY2VtZW50J1xuICAgIF0sIHRoaXMpO1xuXG4gICAgdmFyIGxvYWRlZCA9IGZ1bmN0aW9uKGVyciwgc3R5bGVzaGVldCkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKHN0eWxlc2hlZXQpO1xuICAgICAgICBpZiAodmFsaWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YWxpZC5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fbG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHlsZXNoZWV0ID0gc3R5bGVzaGVldDtcblxuICAgICAgICB2YXIgc291cmNlcyA9IHN0eWxlc2hlZXQuc291cmNlcztcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gc291cmNlcykge1xuICAgICAgICAgICAgdGhpcy5hZGRTb3VyY2UoaWQsIHNvdXJjZXNbaWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHlsZXNoZWV0LnNwcml0ZSkge1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUgPSBuZXcgSW1hZ2VTcHJpdGUoc3R5bGVzaGVldC5zcHJpdGUpO1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUub24oJ2xvYWQnLCB0aGlzLmZpcmUuYmluZCh0aGlzLCAnY2hhbmdlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZSA9IG5ldyBHbHlwaFNvdXJjZShzdHlsZXNoZWV0LmdseXBocywgdGhpcy5nbHlwaEF0bGFzKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBpZiAodHlwZW9mIHN0eWxlc2hlZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTihub3JtYWxpemVVUkwoc3R5bGVzaGVldCksIGxvYWRlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnJvd3Nlci5mcmFtZShsb2FkZWQuYmluZCh0aGlzLCBudWxsLCBzdHlsZXNoZWV0KSk7XG4gICAgfVxufVxuXG5TdHlsZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKVxuICAgICAgICAgICAgaWYgKCF0aGlzLnNvdXJjZXNbaWRdLmxvYWRlZCgpKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAodGhpcy5zcHJpdGUgJiYgIXRoaXMuc3ByaXRlLmxvYWRlZCgpKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBfcmVzb2x2ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBpZCwgbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5fbGF5ZXJzID0ge307XG4gICAgICAgIHRoaXMuX29yZGVyICA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zdHlsZXNoZWV0LmxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGF5ZXIgPSBuZXcgU3R5bGVMYXllcih0aGlzLnN0eWxlc2hlZXQubGF5ZXJzW2ldLCB0aGlzLnN0eWxlc2hlZXQuY29uc3RhbnRzIHx8IHt9KTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgICAgIHRoaXMuX29yZGVyLnB1c2gobGF5ZXIuaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsYXlvdXQgcHJvcGVydGllcy5cbiAgICAgICAgZm9yIChpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZUxheW91dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSByZWZlcmVuY2UgYW5kIHBhaW50IHByb3BlcnRpZXMuXG4gICAgICAgIGZvciAoaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLnJlc29sdmVSZWZlcmVuY2UodGhpcy5fbGF5ZXJzKTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZVBhaW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICB9LFxuXG4gICAgX2dyb3VwTGF5ZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdyb3VwO1xuXG4gICAgICAgIHRoaXMuX2dyb3VwcyA9IFtdO1xuXG4gICAgICAgIC8vIFNwbGl0IGludG8gZ3JvdXBzIG9mIGNvbnNlY3V0aXZlIHRvcC1sZXZlbCBsYXllcnMgd2l0aCB0aGUgc2FtZSBzb3VyY2UuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fb3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1t0aGlzLl9vcmRlcltpXV07XG5cbiAgICAgICAgICAgIGlmICghZ3JvdXAgfHwgbGF5ZXIuc291cmNlICE9PSBncm91cC5zb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwLnNvdXJjZSA9IGxheWVyLnNvdXJjZTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ncm91cHMucHVzaChncm91cCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdyb3VwLnB1c2gobGF5ZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9icm9hZGNhc3RMYXllcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb3JkZXJlZCA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgb3JkZXJlZC5wdXNoKHRoaXMuX2xheWVyc1tpZF0uanNvbigpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoJ3NldCBsYXllcnMnLCBvcmRlcmVkKTtcbiAgICB9LFxuXG4gICAgX2Nhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpIHJldHVybjtcblxuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLmNhc2NhZGUoY2xhc3Nlcywgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICB0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbiB8fCB7fSxcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICB9LFxuXG4gICAgX3JlY2FsY3VsYXRlOiBmdW5jdGlvbih6KSB7XG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuc291cmNlcylcbiAgICAgICAgICAgIHRoaXMuc291cmNlc1tpZF0udXNlZCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZVpvb21IaXN0b3J5KHopO1xuXG4gICAgICAgIHRoaXMucmFzdGVyRmFkZUR1cmF0aW9uID0gMzAwO1xuICAgICAgICBmb3IgKGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgdmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcblxuICAgICAgICAgICAgaWYgKGxheWVyLnJlY2FsY3VsYXRlKHosIHRoaXMuem9vbUhpc3RvcnkpICYmIGxheWVyLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1heFpvb21UcmFuc2l0aW9uRHVyYXRpb24gPSAzMDA7XG4gICAgICAgIGlmIChNYXRoLmZsb29yKHRoaXMueikgIT09IE1hdGguZmxvb3IoeikpIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uTG9vcC5zZXQobWF4Wm9vbVRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnogPSB6O1xuICAgICAgICB0aGlzLmZpcmUoJ3pvb20nKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVpvb21IaXN0b3J5OiBmdW5jdGlvbih6KSB7XG5cbiAgICAgICAgdmFyIHpoID0gdGhpcy56b29tSGlzdG9yeTtcblxuICAgICAgICBpZiAoemgubGFzdEludGVnZXJab29tID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGZpcnN0IHRpbWVcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbSA9IE1hdGguZmxvb3Ioeik7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb21UaW1lID0gMDtcbiAgICAgICAgICAgIHpoLmxhc3Rab29tID0gejtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgYW4gaW50ZWdlciB6b29tIGxldmVsIGFzIHBhc3NlZCBzaW5jZSB0aGUgbGFzdCBmcmFtZVxuICAgICAgICAvLyBhbmQgaWYgeWVzLCByZWNvcmQgaXQgd2l0aCB0aGUgdGltZS4gVXNlZCBmb3IgdHJhbnNpdGlvbmluZyBwYXR0ZXJucy5cbiAgICAgICAgaWYgKE1hdGguZmxvb3IoemgubGFzdFpvb20pIDwgTWF0aC5mbG9vcih6KSkge1xuICAgICAgICAgICAgemgubGFzdEludGVnZXJab29tID0gTWF0aC5mbG9vcih6KTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoTWF0aC5mbG9vcih6aC5sYXN0Wm9vbSkgPiBNYXRoLmZsb29yKHopKSB7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb20gPSBNYXRoLmZsb29yKHogKyAxKTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgemgubGFzdFpvb20gPSB6O1xuICAgIH0sXG5cbiAgICBhZGRTb3VyY2U6IGZ1bmN0aW9uKGlkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMuc291cmNlc1tpZF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBpcyBhbHJlYWR5IGEgc291cmNlIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIHNvdXJjZSA9IFNvdXJjZS5jcmVhdGUoc291cmNlKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2lkXSA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlLmlkID0gaWQ7XG4gICAgICAgIHNvdXJjZS5zdHlsZSA9IHRoaXM7XG4gICAgICAgIHNvdXJjZS5kaXNwYXRjaGVyID0gdGhpcy5kaXNwYXRjaGVyO1xuICAgICAgICBzb3VyY2UuZ2x5cGhBdGxhcyA9IHRoaXMuZ2x5cGhBdGxhcztcbiAgICAgICAgc291cmNlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCdjaGFuZ2UnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUucmVtb3ZlJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudCk7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLmFkZCcsIHtzb3VyY2U6IHNvdXJjZX0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgc291cmNlIGZyb20gdGhpcyBzdHlsZXNoZWV0LCBnaXZlbiBpdHMgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBzb3VyY2UgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMge1N0eWxlfSB0aGlzIHN0eWxlXG4gICAgICogQHRocm93cyB7RXJyb3J9IGlmIG5vIHNvdXJjZSBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlU291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHNvdXJjZSB3aXRoIHRoaXMgSUQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgIHNvdXJjZVxuICAgICAgICAgICAgLm9mZignbG9hZCcsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZignY2hhbmdlJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5hZGQnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ3RpbGUuZXJyb3InLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KTtcbiAgICAgICAgdGhpcy5maXJlKCdzb3VyY2UucmVtb3ZlJywge3NvdXJjZTogc291cmNlfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzb3VyY2UgYnkgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBkZXNpcmVkIHNvdXJjZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHNvdXJjZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0U291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgbGF5ZXIgdG8gdGhlIG1hcCBzdHlsZS4gVGhlIGxheWVyIHdpbGwgYmUgaW5zZXJ0ZWQgYmVmb3JlIHRoZSBsYXllciB3aXRoXG4gICAgICogSUQgYGJlZm9yZWAsIG9yIGFwcGVuZGVkIGlmIGBiZWZvcmVgIGlzIG9taXR0ZWQuXG4gICAgICogQHBhcmFtIHtTdHlsZUxheWVyfE9iamVjdH0gbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGJlZm9yZSAgSUQgb2YgYW4gZXhpc3RpbmcgbGF5ZXIgdG8gaW5zZXJ0IGJlZm9yZVxuICAgICAqIEBmaXJlcyBsYXllci5hZGRcbiAgICAgKiBAcmV0dXJucyB7U3R5bGV9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZExheWVyOiBmdW5jdGlvbihsYXllciwgYmVmb3JlKSB7XG4gICAgICAgIGlmICh0aGlzLl9sYXllcnNbbGF5ZXIuaWRdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgYWxyZWFkeSBhIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKGxheWVyIGluc3RhbmNlb2YgU3R5bGVMYXllcikpIHtcbiAgICAgICAgICAgIGxheWVyID0gbmV3IFN0eWxlTGF5ZXIobGF5ZXIsIHRoaXMuc3R5bGVzaGVldC5jb25zdGFudHMgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgdGhpcy5fb3JkZXIuc3BsaWNlKGJlZm9yZSA/IHRoaXMuX29yZGVyLmluZGV4T2YoYmVmb3JlKSA6IEluZmluaXR5LCAwLCBsYXllci5pZCk7XG4gICAgICAgIGxheWVyLnJlc29sdmVMYXlvdXQoKTtcbiAgICAgICAgbGF5ZXIucmVzb2x2ZVJlZmVyZW5jZSh0aGlzLl9sYXllcnMpO1xuICAgICAgICBsYXllci5yZXNvbHZlUGFpbnQoKTtcbiAgICAgICAgdGhpcy5fZ3JvdXBMYXllcnMoKTtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuZmlyZSgnbGF5ZXIuYWRkJywge2xheWVyOiBsYXllcn0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgbGF5ZXIgZnJvbSB0aGlzIHN0eWxlc2hlZXQsIGdpdmVuIGl0cyBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGxheWVyIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtTdHlsZX0gdGhpcyBzdHlsZVxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBsYXllciBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XG4gICAgICAgIGlmIChsYXllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fbGF5ZXJzW2ldLnJlZiA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxheWVyKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xuICAgICAgICB0aGlzLl9vcmRlci5zcGxpY2UodGhpcy5fb3JkZXIuaW5kZXhPZihpZCksIDEpO1xuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5maXJlKCdsYXllci5yZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllciBieSBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGRlc2lyZWQgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyB7TGF5ZXJ9IGxheWVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXllcjogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xheWVyc1tpZF07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIElmIGEgbGF5ZXIgaGFzIGEgYHJlZmAgcHJvcGVydHkgdGhhdCBtYWtlcyBpdCBkZXJpdmUgc29tZSB2YWx1ZXNcbiAgICAgKiBmcm9tIGFub3RoZXIgbGF5ZXIsIHJldHVybiB0aGF0IHJlZmVyZW50IGxheWVyLiBPdGhlcndpc2UsXG4gICAgICogcmV0dXJucyB0aGUgbGF5ZXIgaXRzZWxmLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZCB0aGUgbGF5ZXIncyBpZFxuICAgICAqIEByZXR1cm5zIHtMYXllcn0gdGhlIHJlZmVyZW50IGxheWVyIG9yIHRoZSBsYXllciBpdHNlbGZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldFJlZmVyZW50TGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoaWQpO1xuICAgICAgICBpZiAobGF5ZXIucmVmKSB7XG4gICAgICAgICAgICBsYXllciA9IHRoaXMuZ2V0TGF5ZXIobGF5ZXIucmVmKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfSxcblxuICAgIHNldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIsIGZpbHRlcikge1xuICAgICAgICBsYXllciA9IHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcik7XG4gICAgICAgIGxheWVyLmZpbHRlciA9IGZpbHRlcjtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnJlbG9hZCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllcidzIGZpbHRlciBvYmplY3RcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbGF5ZXIgdGhlIGxheWVyIHRvIGluc3BlY3RcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIGxheWVyJ3MgZmlsdGVyLCBpZiBhbnlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZmlsdGVyO1xuICAgIH0sXG5cbiAgICBzZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIGxheWVyID0gdGhpcy5nZXRSZWZlcmVudExheWVyKGxheWVyKTtcbiAgICAgICAgbGF5ZXIuc2V0TGF5b3V0UHJvcGVydHkobmFtZSwgdmFsdWUpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2xheWVyLnNvdXJjZV0ucmVsb2FkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhIGxheW91dCBwcm9wZXJ0eSdzIHZhbHVlIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBsYXllciB0aGUgbGF5ZXIgdG8gaW5zcGVjdFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIHByb3BlcnR5IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZ2V0TGF5b3V0UHJvcGVydHkobmFtZSk7XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSwga2xhc3MpIHtcbiAgICAgICAgdGhpcy5nZXRMYXllcihsYXllcikuc2V0UGFpbnRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihsYXllciwgbmFtZSwga2xhc3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGF5ZXIobGF5ZXIpLmdldFBhaW50UHJvcGVydHkobmFtZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihjb29yZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICAgICAgdmFyIGVycm9yID0gbnVsbDtcblxuICAgICAgICBpZiAocGFyYW1zLmxheWVyKSB7XG4gICAgICAgICAgICBwYXJhbXMubGF5ZXIgPSB7IGlkOiBwYXJhbXMubGF5ZXIgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHV0aWwuYXN5bmNFYWNoKE9iamVjdC5rZXlzKHRoaXMuc291cmNlcyksIGZ1bmN0aW9uKGlkLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgICAgICBzb3VyY2UuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBmdW5jdGlvbihlcnIsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIGZlYXR1cmVzID0gZmVhdHVyZXMuY29uY2F0KHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycikgZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LmJpbmQodGhpcyksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuXG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBmZWF0dXJlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmxheWVyID0gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZlYXR1cmU7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXIucmVtb3ZlKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVTb3VyY2VzOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZXNbaWRdLnVwZGF0ZSh0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9yZWRvUGxhY2VtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXS5yZWRvUGxhY2VtZW50KSB0aGlzLnNvdXJjZXNbaWRdLnJlZG9QbGFjZW1lbnQoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfZm9yd2FyZFNvdXJjZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzb3VyY2U6IGUudGFyZ2V0fSwgZSkpO1xuICAgIH0sXG5cbiAgICBfZm9yd2FyZFRpbGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoZS50eXBlLCB1dGlsLmV4dGVuZCh7c291cmNlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgLy8gQ2FsbGJhY2tzIGZyb20gd2ViIHdvcmtlcnNcblxuICAgICdnZXQgc3ByaXRlIGpzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgeyBzcHJpdGU6IHNwcml0ZS5kYXRhLCByZXRpbmE6IHNwcml0ZS5yZXRpbmEgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7IHNwcml0ZTogc3ByaXRlLmRhdGEsIHJldGluYTogc3ByaXRlLnJldGluYSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgICdnZXQgaWNvbnMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgdmFyIHNwcml0ZUF0bGFzID0gdGhpcy5zcHJpdGVBdGxhcztcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHNwcml0ZSk7XG4gICAgICAgICAgICBzcHJpdGVBdGxhcy5hZGRJY29ucyhwYXJhbXMuaWNvbnMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwcml0ZS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLnNldFNwcml0ZShzcHJpdGUpO1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLmFkZEljb25zKHBhcmFtcy5pY29ucywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2dldCBnbHlwaHMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2x5cGhTb3VyY2UuZ2V0U2ltcGxlR2x5cGhzKHBhcmFtcy5mb250c3RhY2ssIHBhcmFtcy5jb2RlcG9pbnRzLCBwYXJhbXMudWlkLCBjYWxsYmFjayk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmV4cG9ydHMucmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb25zdGFudHMpIHtcbiAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlWzBdID09PSAnQCcgPyBjb25zdGFudHNbdmFsdWVdIDogdmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIGk7XG5cbiAgICB2YWx1ZSA9IHJlc29sdmUodmFsdWUpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtpXSBpbiBjb25zdGFudHMpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtpXSA9IHJlc29sdmUodmFsdWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHZhbHVlID0gdXRpbC5leHRlbmQoe30sIHZhbHVlKTtcbiAgICAgICAgdmFsdWUuc3RvcHMgPSB2YWx1ZS5zdG9wcy5zbGljZSgpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5zdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHZhbHVlLnN0b3BzW2ldWzFdIGluIGNvbnN0YW50cykge1xuICAgICAgICAgICAgICAgIHZhbHVlLnN0b3BzW2ldID0gW1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXVswXSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS5zdG9wc1tpXVsxXSlcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0cy5yZXNvbHZlQWxsID0gZnVuY3Rpb24gKHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIGlmICghY29uc3RhbnRzKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcblxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIGZvciAodmFyIGtleSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gZXhwb3J0cy5yZXNvbHZlKHByb3BlcnRpZXNba2V5XSwgY29uc3RhbnRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhcnNlQ1NTQ29sb3IgPSByZXF1aXJlKCdjc3Njb2xvcnBhcnNlcicpLnBhcnNlQ1NTQ29sb3I7XG52YXIgbWFwYm94R0xGdW5jdGlvbiA9IHJlcXVpcmUoJ21hcGJveC1nbC1mdW5jdGlvbicpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZURlY2xhcmF0aW9uO1xuXG5mdW5jdGlvbiBTdHlsZURlY2xhcmF0aW9uKHJlZmVyZW5jZSwgdmFsdWUpIHtcbiAgICB0aGlzLnR5cGUgPSByZWZlcmVuY2UudHlwZTtcbiAgICB0aGlzLnRyYW5zaXRpb25hYmxlID0gcmVmZXJlbmNlLnRyYW5zaXRpb247XG5cbiAgICAvLyBpbW11dGFibGUgcmVwcmVzZW50YXRpb24gb2YgdmFsdWUuIHVzZWQgZm9yIGNvbXBhcmlzb25cbiAgICB0aGlzLmpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbiAgICBpZiAodGhpcy50eXBlICE9PSAnY29sb3InKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBwcmVwYXJlQ29sb3JGdW5jdGlvbih2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHBhcnNlQ29sb3IodmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChyZWZlcmVuY2UuZnVuY3Rpb24gPT09ICdpbnRlcnBvbGF0ZWQnKSB7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlID0gbWFwYm94R0xGdW5jdGlvbi5pbnRlcnBvbGF0ZWQodGhpcy52YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jYWxjdWxhdGUgPSBtYXBib3hHTEZ1bmN0aW9uWydwaWVjZXdpc2UtY29uc3RhbnQnXSh0aGlzLnZhbHVlKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZS50cmFuc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZSA9IHRyYW5zaXRpb25lZCh0aGlzLmNhbGN1bGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb25lZChjYWxjdWxhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeiwgemgsIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBmcmFjdGlvbiA9IHogJSAxO1xuICAgICAgICB2YXIgdCA9IE1hdGgubWluKChEYXRlLm5vdygpIC0gemgubGFzdEludGVnZXJab29tVGltZSkgLyBkdXJhdGlvbiwgMSk7XG4gICAgICAgIHZhciBmcm9tU2NhbGUgPSAxO1xuICAgICAgICB2YXIgdG9TY2FsZSA9IDE7XG4gICAgICAgIHZhciBtaXgsIGZyb20sIHRvO1xuXG4gICAgICAgIGlmICh6ID4gemgubGFzdEludGVnZXJab29tKSB7XG4gICAgICAgICAgICBtaXggPSBmcmFjdGlvbiArICgxIC0gZnJhY3Rpb24pICogdDtcbiAgICAgICAgICAgIGZyb21TY2FsZSAqPSAyO1xuICAgICAgICAgICAgZnJvbSA9IGNhbGN1bGF0ZSh6IC0gMSk7XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1peCA9IDEgLSAoMSAtIHQpICogZnJhY3Rpb247XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgICAgIGZyb20gPSBjYWxjdWxhdGUoeiArIDEpO1xuICAgICAgICAgICAgZnJvbVNjYWxlIC89IDI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgIGZyb21TY2FsZTogZnJvbVNjYWxlLFxuICAgICAgICAgICAgdG86IHRvLFxuICAgICAgICAgICAgdG9TY2FsZTogdG9TY2FsZSxcbiAgICAgICAgICAgIHQ6IG1peFxuICAgICAgICB9O1xuICAgIH07XG59XG5cbnZhciBjb2xvckNhY2hlID0ge307XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3IodmFsdWUpIHtcbiAgICBpZiAoY29sb3JDYWNoZVt2YWx1ZV0pIHJldHVybiBjb2xvckNhY2hlW3ZhbHVlXTtcbiAgICB2YXIgY29sb3IgPSBwcmVwYXJlQ29sb3IocGFyc2VDU1NDb2xvcih2YWx1ZSkpO1xuICAgIGNvbG9yQ2FjaGVbdmFsdWVdID0gY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3IoYykge1xuICAgIHJldHVybiBbY1swXSAvIDI1NSwgY1sxXSAvIDI1NSwgY1syXSAvIDI1NSwgY1szXSAvIDFdO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3JGdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIHV0aWwuZXh0ZW5kKHt9LCBmLCB7c3RvcHM6IGYuc3RvcHMubWFwKGZ1bmN0aW9uKHN0b3ApIHtcbiAgICAgICAgcmV0dXJuIFtzdG9wWzBdLCBwYXJzZUNvbG9yKHN0b3BbMV0pXTtcbiAgICB9KX0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbicpO1xuXG52YXIgbG9va3VwID0ge1xuICAgIHBhaW50OiB7fSxcbiAgICBsYXlvdXQ6IHt9XG59O1xuXG5yZWZlcmVuY2UubGF5ZXIudHlwZS52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih0eXBlKSB7XG4gICAgbG9va3VwLnBhaW50W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsncGFpbnRfJyArIHR5cGVdKTtcbiAgICBsb29rdXAubGF5b3V0W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsnbGF5b3V0XycgKyB0eXBlXSk7XG59KTtcblxuZnVuY3Rpb24gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZSkge1xuICAgIGZ1bmN0aW9uIFN0eWxlRGVjbGFyYXRpb25TZXQocHJvcGVydGllcywgY29uc3RhbnRzKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IHt9O1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9ucyA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2NvbnN0YW50cyA9IGNvbnN0YW50cztcblxuICAgICAgICBmb3IgKHZhciBrIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXNba10gPSBTdHlsZUNvbnN0YW50LnJlc29sdmUocHJvcGVydGllc1trXSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKHJlZmVyZW5jZSkuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgICAgIHZhciBwcm9wZXJ0eSA9IHJlZmVyZW5jZVtrXTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3R5bGVEZWNsYXJhdGlvblNldC5wcm90b3R5cGUsIGssIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlc1trXSA9IG5ldyBTdHlsZURlY2xhcmF0aW9uKHByb3BlcnR5LCBTdHlsZUNvbnN0YW50LnJlc29sdmUodiwgdGhpcy5fY29uc3RhbnRzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzW2tdLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocHJvcGVydHkudHJhbnNpdGlvbikge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLCBrICsgJy10cmFuc2l0aW9uJywge1xuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2l0aW9uc1trXSA9IHY7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNpdGlvbnNba107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xuICAgIH07XG5cbiAgICBTdHlsZURlY2xhcmF0aW9uU2V0LnByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24oaywgZ2xvYmFsKSB7XG4gICAgICAgIHZhciB0ID0gdGhpcy5fdHJhbnNpdGlvbnNba10gfHwge307XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogdXRpbC5jb2FsZXNjZSh0LmR1cmF0aW9uLCBnbG9iYWwuZHVyYXRpb24sIDMwMCksXG4gICAgICAgICAgICBkZWxheTogdXRpbC5jb2FsZXNjZSh0LmRlbGF5LCBnbG9iYWwuZGVsYXksIDApXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgIGZvciAodmFyIHYgaW4gdGhpcy5fdmFsdWVzKSB7XG4gICAgICAgICAgICByZXN1bHRbdl0gPSB0aGlzLl92YWx1ZXNbdl0udmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMuX3RyYW5zaXRpb25zKSB7XG4gICAgICAgICAgICByZXN1bHRbdCArICctdHJhbnNpdGlvbiddID0gdGhpcy5fdHJhbnNpdGlvbnNbdl07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICByZXR1cm4gU3R5bGVEZWNsYXJhdGlvblNldDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihyZW5kZXJUeXBlLCBsYXllclR5cGUsIHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIHJldHVybiBuZXcgbG9va3VwW3JlbmRlclR5cGVdW2xheWVyVHlwZV0ocHJvcGVydGllcywgY29uc3RhbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZVRyYW5zaXRpb24gPSByZXF1aXJlKCcuL3N0eWxlX3RyYW5zaXRpb24nKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uU2V0ID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbl9zZXQnKTtcbnZhciBMYXlvdXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9sYXlvdXRfcHJvcGVydGllcycpO1xudmFyIFBhaW50UHJvcGVydGllcyA9IHJlcXVpcmUoJy4vcGFpbnRfcHJvcGVydGllcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFN0eWxlTGF5ZXIobGF5ZXIsIGNvbnN0YW50cykge1xuICAgIHRoaXMuX2xheWVyID0gbGF5ZXI7XG4gICAgdGhpcy5fY29uc3RhbnRzID0gY29uc3RhbnRzO1xuXG4gICAgdGhpcy5pZCA9IGxheWVyLmlkO1xuICAgIHRoaXMucmVmID0gbGF5ZXIucmVmO1xuXG4gICAgLy8gUmVzb2x2ZWQgYW5kIGNhc2NhZGVkIHBhaW50IHByb3BlcnRpZXMuXG4gICAgdGhpcy5fcmVzb2x2ZWQgPSB7fTsgLy8gY2xhc3MgbmFtZSAtPiBTdHlsZURlY2xhcmF0aW9uU2V0XG4gICAgdGhpcy5fY2FzY2FkZWQgPSB7fTsgLy8gcHJvcGVydHkgbmFtZSAtPiBTdHlsZVRyYW5zaXRpb25cblxuICAgIHRoaXMuYXNzaWduKGxheWVyKTtcbn1cblxuU3R5bGVMYXllci5wcm90b3R5cGUgPSB7XG4gICAgcmVzb2x2ZUxheW91dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5yZWYpIHtcbiAgICAgICAgICAgIHRoaXMubGF5b3V0ID0gbmV3IExheW91dFByb3BlcnRpZXNbdGhpcy50eXBlXShcbiAgICAgICAgICAgICAgICBTdHlsZUNvbnN0YW50LnJlc29sdmVBbGwodGhpcy5fbGF5ZXIubGF5b3V0LCB0aGlzLl9jb25zdGFudHMpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMubGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5sYXlvdXQuaGFzT3duUHJvcGVydHkoJ3RleHQtcm90YXRpb24tYWxpZ25tZW50JykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPSAnbWFwJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxheW91dC5oYXNPd25Qcm9wZXJ0eSgnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnc3ltYm9sLWF2b2lkLWVkZ2VzJ10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldExheW91dFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmxheW91dFtuYW1lXSA9IFN0eWxlQ29uc3RhbnQucmVzb2x2ZSh2YWx1ZSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICB9LFxuXG4gICAgZ2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGF5b3V0W25hbWVdO1xuICAgIH0sXG5cbiAgICByZXNvbHZlUmVmZXJlbmNlOiBmdW5jdGlvbihsYXllcnMpIHtcbiAgICAgICAgaWYgKHRoaXMucmVmKSB7XG4gICAgICAgICAgICB0aGlzLmFzc2lnbihsYXllcnNbdGhpcy5yZWZdKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZXNvbHZlUGFpbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBwIGluIHRoaXMuX2xheWVyKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBwLm1hdGNoKC9ecGFpbnQoPzpcXC4oLiopKT8kLyk7XG4gICAgICAgICAgICBpZiAoIW1hdGNoKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZWRbbWF0Y2hbMV0gfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHRoaXMuX2xheWVyW3BdLCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucykge1xuICAgICAgICAgICAgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHt9LCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgICAgIGRlY2xhcmF0aW9uc1tuYW1lXSA9IHZhbHVlO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucylcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBkZWNsYXJhdGlvbnNbbmFtZV07XG4gICAgfSxcblxuICAgIGNhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMsIGdsb2JhbFRyYW5zLCBhbmltYXRpb25Mb29wKSB7XG4gICAgICAgIGZvciAodmFyIGtsYXNzIGluIHRoaXMuX3Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpZiAoa2xhc3MgIT09IFwiXCIgJiYgIWNsYXNzZXNba2xhc3NdKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3NdLFxuICAgICAgICAgICAgICAgIHZhbHVlcyA9IGRlY2xhcmF0aW9ucy52YWx1ZXMoKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgayBpbiB2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RGVjbGFyYXRpb24gPSB2YWx1ZXNba107XG4gICAgICAgICAgICAgICAgdmFyIG9sZFRyYW5zaXRpb24gPSBvcHRpb25zLnRyYW5zaXRpb24gPyB0aGlzLl9jYXNjYWRlZFtrXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IHRyYW5zaXRpb24gaWYgdGhlIGRlY2xhcmF0aW9uIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpZiAoIW9sZFRyYW5zaXRpb24gfHwgb2xkVHJhbnNpdGlvbi5kZWNsYXJhdGlvbi5qc29uICE9PSBuZXdEZWNsYXJhdGlvbi5qc29uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdTdHlsZVRyYW5zID0gZGVjbGFyYXRpb25zLnRyYW5zaXRpb24oaywgZ2xvYmFsVHJhbnMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMuX2Nhc2NhZGVkW2tdID1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTdHlsZVRyYW5zaXRpb24obmV3RGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIG5ld1N0eWxlVHJhbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJ1biB0aGUgYW5pbWF0aW9uIGxvb3AgdW50aWwgdGhlIGVuZCBvZiB0aGUgdHJhbnNpdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld1RyYW5zaXRpb24uaW5zdGFudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdUcmFuc2l0aW9uLmxvb3BJRCA9IGFuaW1hdGlvbkxvb3Auc2V0KG5ld1RyYW5zaXRpb24uZW5kVGltZSAtIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkxvb3AuY2FuY2VsKG9sZFRyYW5zaXRpb24ubG9vcElEKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZWNhbGN1bGF0ZTogZnVuY3Rpb24oeiwgem9vbUhpc3RvcnkpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLnR5cGUsXG4gICAgICAgICAgICBjYWxjdWxhdGVkID0gdGhpcy5wYWludCA9IG5ldyBQYWludFByb3BlcnRpZXNbdHlwZV0oKTtcblxuICAgICAgICBmb3IgKHZhciBrIGluIHRoaXMuX2Nhc2NhZGVkKSB7XG4gICAgICAgICAgICBjYWxjdWxhdGVkW2tdID0gdGhpcy5fY2FzY2FkZWRba10uYXQoeiwgem9vbUhpc3RvcnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRkZW4gPSAodGhpcy5taW56b29tICYmIHogPCB0aGlzLm1pbnpvb20pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHRoaXMubWF4em9vbSAmJiB6ID49IHRoaXMubWF4em9vbSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpbmNsdWRlIHZpc2liaWxpdHkgY2hlY2sgZm9yIG5vbi1idWNrZXRlZCBiYWNrZ3JvdW5kIGxheWVyc1xuICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmxheW91dC52aXNpYmlsaXR5ID09PSAnbm9uZScpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgaWYgKChjYWxjdWxhdGVkWyd0ZXh0LW9wYWNpdHknXSA9PT0gMCB8fCAhdGhpcy5sYXlvdXRbJ3RleHQtZmllbGQnXSkgJiZcbiAgICAgICAgICAgICAgICAoY2FsY3VsYXRlZFsnaWNvbi1vcGFjaXR5J10gPT09IDAgfHwgIXRoaXMubGF5b3V0WydpY29uLWltYWdlJ10pKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVtdWx0aXBseUxheWVyKGNhbGN1bGF0ZWQsICd0ZXh0Jyk7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihjYWxjdWxhdGVkLCAnaWNvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY2FsY3VsYXRlZFt0eXBlICsgJy1vcGFjaXR5J10gPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZW11bHRpcGx5TGF5ZXIoY2FsY3VsYXRlZCwgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY2FzY2FkZWRbJ2xpbmUtZGFzaGFycmF5J10pIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBsaW5lIGlzIGRhc2hlZCwgc2NhbGUgdGhlIGRhc2ggbGVuZ3RocyBieSB0aGUgbGluZVxuICAgICAgICAgICAgLy8gd2lkdGggYXQgdGhlIHByZXZpb3VzIHJvdW5kIHpvb20gbGV2ZWwuXG4gICAgICAgICAgICB2YXIgZGFzaEFycmF5ID0gY2FsY3VsYXRlZFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICAgICAgICAgIHZhciBsaW5lV2lkdGggPSB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddID9cbiAgICAgICAgICAgICAgICB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddLmF0KE1hdGguZmxvb3IoeiksIEluZmluaXR5KSA6XG4gICAgICAgICAgICAgICAgY2FsY3VsYXRlZFsnbGluZS13aWR0aCddO1xuXG4gICAgICAgICAgICBkYXNoQXJyYXkuZnJvbVNjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgICAgIGRhc2hBcnJheS50b1NjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfSxcblxuICAgIGFzc2lnbjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKGxheWVyLFxuICAgICAgICAgICAgWyd0eXBlJywgJ3NvdXJjZScsICdzb3VyY2UtbGF5ZXInLFxuICAgICAgICAgICAgJ21pbnpvb20nLCAnbWF4em9vbScsICdmaWx0ZXInLFxuICAgICAgICAgICAgJ2xheW91dCddKSk7XG4gICAgfSxcblxuICAgIGpzb246IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdXRpbC5leHRlbmQoe30sXG4gICAgICAgICAgICB0aGlzLl9sYXllcixcbiAgICAgICAgICAgIHV0aWwucGljayh0aGlzLFxuICAgICAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJyxcbiAgICAgICAgICAgICAgICAnbWluem9vbScsICdtYXh6b29tJywgJ2ZpbHRlcicsXG4gICAgICAgICAgICAgICAgJ2xheW91dCcsICdwYWludCddKSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcHJlbXVsdGlwbHlMYXllcihsYXllciwgdHlwZSkge1xuICAgIHZhciBjb2xvclByb3AgPSB0eXBlICsgJy1jb2xvcicsXG4gICAgICAgIGhhbG9Qcm9wID0gdHlwZSArICctaGFsby1jb2xvcicsXG4gICAgICAgIG91dGxpbmVQcm9wID0gdHlwZSArICctb3V0bGluZS1jb2xvcicsXG4gICAgICAgIGNvbG9yID0gbGF5ZXJbY29sb3JQcm9wXSxcbiAgICAgICAgaGFsb0NvbG9yID0gbGF5ZXJbaGFsb1Byb3BdLFxuICAgICAgICBvdXRsaW5lQ29sb3IgPSBsYXllcltvdXRsaW5lUHJvcF0sXG4gICAgICAgIG9wYWNpdHkgPSBsYXllclt0eXBlICsgJy1vcGFjaXR5J107XG5cbiAgICB2YXIgY29sb3JPcGFjaXR5ID0gY29sb3IgJiYgKG9wYWNpdHkgKiBjb2xvclszXSk7XG4gICAgdmFyIGhhbG9PcGFjaXR5ID0gaGFsb0NvbG9yICYmIChvcGFjaXR5ICogaGFsb0NvbG9yWzNdKTtcbiAgICB2YXIgb3V0bGluZU9wYWNpdHkgPSBvdXRsaW5lQ29sb3IgJiYgKG9wYWNpdHkgKiBvdXRsaW5lQ29sb3JbM10pO1xuXG4gICAgaWYgKGNvbG9yT3BhY2l0eSAhPT0gdW5kZWZpbmVkICYmIGNvbG9yT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbY29sb3JQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW2NvbG9yWzBdLCBjb2xvclsxXSwgY29sb3JbMl0sIGNvbG9yT3BhY2l0eV0pO1xuICAgIH1cbiAgICBpZiAoaGFsb09wYWNpdHkgIT09IHVuZGVmaW5lZCAmJiBoYWxvT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbaGFsb1Byb3BdID0gdXRpbC5wcmVtdWx0aXBseShbaGFsb0NvbG9yWzBdLCBoYWxvQ29sb3JbMV0sIGhhbG9Db2xvclsyXSwgaGFsb09wYWNpdHldKTtcbiAgICB9XG4gICAgaWYgKG91dGxpbmVPcGFjaXR5ICE9PSB1bmRlZmluZWQgJiYgb3V0bGluZU9wYWNpdHkgPCAxKSB7XG4gICAgICAgIGxheWVyW291dGxpbmVQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW291dGxpbmVDb2xvclswXSwgb3V0bGluZUNvbG9yWzFdLCBvdXRsaW5lQ29sb3JbMl0sIG91dGxpbmVPcGFjaXR5XSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlVHJhbnNpdGlvbjtcblxuLypcbiAqIFJlcHJlc2VudHMgYSB0cmFuc2l0aW9uIGJldHdlZW4gdHdvIGRlY2xhcmF0aW9uc1xuICovXG5mdW5jdGlvbiBTdHlsZVRyYW5zaXRpb24oZGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIHZhbHVlKSB7XG5cbiAgICB0aGlzLmRlY2xhcmF0aW9uID0gZGVjbGFyYXRpb247XG4gICAgdGhpcy5zdGFydFRpbWUgPSB0aGlzLmVuZFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgdmFyIHR5cGUgPSBkZWNsYXJhdGlvbi50eXBlO1xuICAgIGlmICgodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ2FycmF5JykgJiYgZGVjbGFyYXRpb24udHJhbnNpdGlvbmFibGUpIHtcbiAgICAgICAgdGhpcy5pbnRlcnAgPSBpbnRlcnBab29tVHJhbnNpdGlvbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW50ZXJwID0gaW50ZXJwb2xhdGVbdHlwZV07XG4gICAgfVxuXG4gICAgdGhpcy5vbGRUcmFuc2l0aW9uID0gb2xkVHJhbnNpdGlvbjtcbiAgICB0aGlzLmR1cmF0aW9uID0gdmFsdWUuZHVyYXRpb24gfHwgMDtcbiAgICB0aGlzLmRlbGF5ID0gdmFsdWUuZGVsYXkgfHwgMDtcblxuICAgIGlmICghdGhpcy5pbnN0YW50KCkpIHtcbiAgICAgICAgdGhpcy5lbmRUaW1lID0gdGhpcy5zdGFydFRpbWUgKyB0aGlzLmR1cmF0aW9uICsgdGhpcy5kZWxheTtcbiAgICAgICAgdGhpcy5lYXNlID0gdXRpbC5lYXNlQ3ViaWNJbk91dDtcbiAgICB9XG5cbiAgICBpZiAob2xkVHJhbnNpdGlvbiAmJiBvbGRUcmFuc2l0aW9uLmVuZFRpbWUgPD0gdGhpcy5zdGFydFRpbWUpIHtcbiAgICAgICAgLy8gT2xkIHRyYW5zaXRpb24gaXMgZG9uZSBydW5uaW5nLCBzbyB3ZSBjYW5cbiAgICAgICAgLy8gZGVsZXRlIGl0cyByZWZlcmVuY2UgdG8gaXRzIG9sZCB0cmFuc2l0aW9uLlxuXG4gICAgICAgIGRlbGV0ZSBvbGRUcmFuc2l0aW9uLm9sZFRyYW5zaXRpb247XG4gICAgfVxufVxuXG5TdHlsZVRyYW5zaXRpb24ucHJvdG90eXBlLmluc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMub2xkVHJhbnNpdGlvbiB8fCAhdGhpcy5pbnRlcnAgfHwgKHRoaXMuZHVyYXRpb24gPT09IDAgJiYgdGhpcy5kZWxheSA9PT0gMCk7XG59O1xuXG4vKlxuICogUmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgdHJhbnNpdGlvbmluZyBwcm9wZXJ0eSBhdCB6b29tIGxldmVsIGB6YCBhbmQgb3B0aW9uYWwgdGltZSBgdGBcbiAqL1xuU3R5bGVUcmFuc2l0aW9uLnByb3RvdHlwZS5hdCA9IGZ1bmN0aW9uKHosIHpvb21IaXN0b3J5LCB0KSB7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLmRlY2xhcmF0aW9uLmNhbGN1bGF0ZSh6LCB6b29tSGlzdG9yeSwgdGhpcy5kdXJhdGlvbik7XG5cbiAgICBpZiAodGhpcy5pbnN0YW50KCkpIHJldHVybiB2YWx1ZTtcblxuICAgIHQgPSB0IHx8IERhdGUubm93KCk7XG5cbiAgICBpZiAodCA8IHRoaXMuZW5kVGltZSkge1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm9sZFRyYW5zaXRpb24uYXQoeiwgem9vbUhpc3RvcnksIHRoaXMuc3RhcnRUaW1lKTtcbiAgICAgICAgdmFyIGVhc2VkID0gdGhpcy5lYXNlKCh0IC0gdGhpcy5zdGFydFRpbWUgLSB0aGlzLmRlbGF5KSAvIHRoaXMuZHVyYXRpb24pO1xuICAgICAgICB2YWx1ZSA9IHRoaXMuaW50ZXJwKG9sZFZhbHVlLCB2YWx1ZSwgZWFzZWQpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcblxufTtcblxuZnVuY3Rpb24gaW50ZXJwWm9vbVRyYW5zaXRpb25lZChmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGZyb20udG8sXG4gICAgICAgIGZyb21TY2FsZTogZnJvbS50b1NjYWxlLFxuICAgICAgICB0bzogdG8udG8sXG4gICAgICAgIHRvU2NhbGU6IHRvLnRvU2NhbGUsXG4gICAgICAgIHQ6IHRcbiAgICB9O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuY2hvcjtcblxuZnVuY3Rpb24gQW5jaG9yKHgsIHksIGFuZ2xlLCBzZWdtZW50KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcblxuICAgIGlmIChzZWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDtcbiAgICB9XG59XG5cbkFuY2hvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBvaW50LnByb3RvdHlwZSk7XG5cbkFuY2hvci5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IEFuY2hvcih0aGlzLngsIHRoaXMueSwgdGhpcy5hbmdsZSwgdGhpcy5zZWdtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQmluUGFjaztcbmZ1bmN0aW9uIEJpblBhY2sod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLmZyZWUgPSBbeyB4OiAwLCB5OiAwLCB3OiB3aWR0aCwgaDogaGVpZ2h0IH1dO1xufVxuXG4vKipcbiAqIFNpbXBsZSBhbGdvcml0aG0gdG8gcmVjdXJzaXZlbHkgbWVyZ2UgdGhlIG5ld2x5IHJlbGVhc2VkIGNlbGwgd2l0aCBpdHNcbiAqIG5laWdoYm9yLiBUaGlzIGRvZXNuJ3QgbWVyZ2UgbW9yZSB0aGFuIHR3byBjZWxscyBhdCBhIHRpbWUsIGFuZCBmYWlsc1xuICogZm9yIGNvbXBsaWNhdGVkIG1lcmdlcy5cbiAqIEBwcml2YXRlXG4gKi9cbkJpblBhY2sucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbihyZWN0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmZyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmZyZWVbaV07XG5cbiAgICAgICAgaWYgKGZyZWUueSA9PT0gcmVjdC55ICYmIGZyZWUuaCA9PT0gcmVjdC5oICYmIGZyZWUueCArIGZyZWUudyA9PT0gcmVjdC54KSB7XG4gICAgICAgICAgICBmcmVlLncgKz0gcmVjdC53O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZnJlZS54ID09PSByZWN0LnggJiYgZnJlZS53ID09PSByZWN0LncgJiYgZnJlZS55ICsgZnJlZS5oID09PSByZWN0LnkpIHtcbiAgICAgICAgICAgIGZyZWUuaCArPSByZWN0Lmg7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWN0LnkgPT09IGZyZWUueSAmJiByZWN0LmggPT09IGZyZWUuaCAmJiByZWN0LnggKyByZWN0LncgPT09IGZyZWUueCkge1xuICAgICAgICAgICAgZnJlZS54ID0gcmVjdC54O1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcblxuICAgICAgICB9IGVsc2UgaWYgKHJlY3QueCA9PT0gZnJlZS54ICYmIHJlY3QudyA9PT0gZnJlZS53ICYmIHJlY3QueSArIHJlY3QuaCA9PT0gZnJlZS55KSB7XG4gICAgICAgICAgICBmcmVlLnkgPSByZWN0Lnk7XG4gICAgICAgICAgICBmcmVlLmggKz0gcmVjdC5oO1xuXG4gICAgICAgIH0gZWxzZSBjb250aW51ZTtcblxuICAgICAgICB0aGlzLmZyZWUuc3BsaWNlKGksIDEpO1xuICAgICAgICB0aGlzLnJlbGVhc2UoZnJlZSk7XG4gICAgICAgIHJldHVybjtcblxuICAgIH1cbiAgICB0aGlzLmZyZWUucHVzaChyZWN0KTtcbn07XG5cbkJpblBhY2sucHJvdG90eXBlLmFsbG9jYXRlID0gZnVuY3Rpb24od2lkdGgsIGhlaWdodCkge1xuICAgIC8vIEZpbmQgdGhlIHNtYWxsZXN0IGZyZWUgcmVjdCBhbmdsZVxuICAgIHZhciByZWN0ID0geyB4OiBJbmZpbml0eSwgeTogSW5maW5pdHksIHc6IEluZmluaXR5LCBoOiBJbmZpbml0eSB9O1xuICAgIHZhciBzbWFsbGVzdCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZWYgPSB0aGlzLmZyZWVbaV07XG4gICAgICAgIGlmICh3aWR0aCA8PSByZWYudyAmJiBoZWlnaHQgPD0gcmVmLmggJiYgcmVmLnkgPD0gcmVjdC55ICYmIHJlZi54IDw9IHJlY3QueCkge1xuICAgICAgICAgICAgcmVjdCA9IHJlZjtcbiAgICAgICAgICAgIHNtYWxsZXN0ID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzbWFsbGVzdCA8IDApIHtcbiAgICAgICAgLy8gVGhlcmUncyBubyBzcGFjZSBsZWZ0IGZvciB0aGlzIGNoYXIuXG4gICAgICAgIHJldHVybiB7IHg6IC0xLCB5OiAtMSB9O1xuICAgIH1cblxuICAgIHRoaXMuZnJlZS5zcGxpY2Uoc21hbGxlc3QsIDEpO1xuXG4gICAgLy8gU2hvcnRlci9Mb25nZXIgQXhpcyBTcGxpdCBSdWxlIChTQVMpXG4gICAgLy8gaHR0cDovL2NsYi5kZW1vbi5maS9maWxlcy9SZWN0YW5nbGVCaW5QYWNrLnBkZiBwLiAxNVxuICAgIC8vIElnbm9yZSB0aGUgZGltZW5zaW9uIG9mIFIgYW5kIGp1c3Qgc3BsaXQgbG9uZyB0aGUgc2hvcnRlciBkaW1lbnNpb25cbiAgICAvLyBTZWUgQWxzbzogaHR0cDovL3d3dy5jcy5wcmluY2V0b24uZWR1L35jaGF6ZWxsZS9wdWJzL2JsYmlucGFja2luZy5wZGZcbiAgICBpZiAocmVjdC53IDwgcmVjdC5oKSB7XG4gICAgICAgIC8vIHNwbGl0IGhvcml6b250YWxseVxuICAgICAgICAvLyArLS0rLS0tK1xuICAgICAgICAvLyB8X198X19ffCAgPC0tIGIxXG4gICAgICAgIC8vICstLS0tLS0rICA8LS0gYjJcbiAgICAgICAgaWYgKHJlY3QudyA+IHdpZHRoKSB0aGlzLmZyZWUucHVzaCh7IHg6IHJlY3QueCArIHdpZHRoLCB5OiByZWN0LnksIHc6IHJlY3QudyAtIHdpZHRoLCBoOiBoZWlnaHQgfSk7XG4gICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHJlY3QudywgaDogcmVjdC5oIC0gaGVpZ2h0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNwbGl0IHZlcnRpY2FsbHlcbiAgICAgICAgLy8gKy0tKy0tLStcbiAgICAgICAgLy8gfF9ffCAgIHwgPC0tIGIxXG4gICAgICAgIC8vICstLXwtLS0rIDwtLSBiMlxuICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IHJlY3QuaCB9KTtcbiAgICAgICAgaWYgKHJlY3QuaCA+IGhlaWdodCkgdGhpcy5mcmVlLnB1c2goeyB4OiByZWN0LngsIHk6IHJlY3QueSArIGhlaWdodCwgdzogd2lkdGgsIGg6IHJlY3QuaCAtIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB4OiByZWN0LngsIHk6IHJlY3QueSwgdzogd2lkdGgsIGg6IGhlaWdodCB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjaGVja01heEFuZ2xlO1xuXG5mdW5jdGlvbiBjaGVja01heEFuZ2xlKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIHdpbmRvd1NpemUsIG1heEFuZ2xlKSB7XG5cbiAgICAvLyBob3Jpem9udGFsIGxhYmVscyBhbHdheXMgcGFzc1xuICAgIGlmIChhbmNob3Iuc2VnbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBwID0gYW5jaG9yO1xuICAgIHZhciBpbmRleCA9IGFuY2hvci5zZWdtZW50ICsgMTtcbiAgICB2YXIgYW5jaG9yRGlzdGFuY2UgPSAwO1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPiAtbGFiZWxMZW5ndGggLyAyKSB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIGlmIChpbmRleCA8IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICBhbmNob3JEaXN0YW5jZSAtPSBsaW5lW2luZGV4XS5kaXN0KHApO1xuICAgICAgICBwID0gbGluZVtpbmRleF07XG4gICAgfVxuXG4gICAgYW5jaG9yRGlzdGFuY2UgKz0gbGluZVtpbmRleF0uZGlzdChsaW5lW2luZGV4ICsgMV0pO1xuICAgIGluZGV4Kys7XG5cbiAgICAvLyBzdG9yZSByZWNlbnQgY29ybmVycyBhbmQgdGhlaXIgdG90YWwgYW5nbGUgZGlmZmVyZW5jZVxuICAgIHZhciByZWNlbnRDb3JuZXJzID0gW107XG4gICAgdmFyIHJlY2VudEFuZ2xlRGVsdGEgPSAwO1xuXG4gICAgLy8gbW92ZSBmb3J3YXJkcyBieSB0aGUgbGVuZ3RoIG9mIHRoZSBsYWJlbCBhbmQgY2hlY2sgYW5nbGVzIGFsb25nIHRoZSB3YXlcbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPCBsYWJlbExlbmd0aCAvIDIpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2luZGV4IC0gMV07XG4gICAgICAgIHZhciBjdXJyZW50ID0gbGluZVtpbmRleF07XG4gICAgICAgIHZhciBuZXh0ID0gbGluZVtpbmRleCArIDFdO1xuXG4gICAgICAgIC8vIHRoZXJlIGlzbid0IGVub3VnaCByb29tIGZvciB0aGUgbGFiZWwgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGxpbmVcbiAgICAgICAgaWYgKCFuZXh0KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIGFuZ2xlRGVsdGEgPSBwcmV2LmFuZ2xlVG8oY3VycmVudCkgLSBjdXJyZW50LmFuZ2xlVG8obmV4dCk7XG4gICAgICAgIC8vIHJlc3RyaWN0IGFuZ2xlIHRvIC1waS4ucGkgcmFuZ2VcbiAgICAgICAgYW5nbGVEZWx0YSA9ICgoYW5nbGVEZWx0YSArIDMgKiBNYXRoLlBJKSAlIChNYXRoLlBJICogMikpIC0gTWF0aC5QSTtcblxuICAgICAgICByZWNlbnRDb3JuZXJzLnB1c2goe1xuICAgICAgICAgICAgZGlzdGFuY2U6IGFuY2hvckRpc3RhbmNlLFxuICAgICAgICAgICAgYW5nbGVEZWx0YTogYW5nbGVEZWx0YVxuICAgICAgICB9KTtcbiAgICAgICAgcmVjZW50QW5nbGVEZWx0YSArPSBhbmdsZURlbHRhO1xuXG4gICAgICAgIC8vIHJlbW92ZSBjb3JuZXJzIHRoYXQgYXJlIGZhciBlbm91Z2ggYXdheSBmcm9tIHRoZSBsaXN0IG9mIHJlY2VudCBhbmNob3JzXG4gICAgICAgIHdoaWxlIChhbmNob3JEaXN0YW5jZSAtIHJlY2VudENvcm5lcnNbMF0uZGlzdGFuY2UgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICByZWNlbnRBbmdsZURlbHRhIC09IHJlY2VudENvcm5lcnMuc2hpZnQoKS5hbmdsZURlbHRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHN1bSBvZiBhbmdsZXMgd2l0aGluIHRoZSB3aW5kb3cgYXJlYSBleGNlZWRzIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuIGNoZWNrIGZhaWxzLlxuICAgICAgICBpZiAoTWF0aC5hYnMocmVjZW50QW5nbGVEZWx0YSkgPiBtYXhBbmdsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGluZGV4Kys7XG4gICAgICAgIGFuY2hvckRpc3RhbmNlICs9IGN1cnJlbnQuZGlzdChuZXh0KTtcbiAgICB9XG5cbiAgICAvLyBubyBwYXJ0IG9mIHRoZSBsaW5lIGhhZCBhbiBhbmdsZSBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gYWxsb3dlZC4gY2hlY2sgcGFzc2VzLlxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsaXBMaW5lO1xuXG5mdW5jdGlvbiBjbGlwTGluZShsaW5lcywgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgY2xpcHBlZExpbmVzID0gW107XG5cbiAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxpbmVzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgIHZhciBsaW5lID0gbGluZXNbbF07XG4gICAgICAgIHZhciBjbGlwcGVkTGluZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcDAgPSBsaW5lW2ldO1xuICAgICAgICAgICAgdmFyIHAxID0gbGluZVtpICsgMV07XG5cblxuICAgICAgICAgICAgaWYgKHAwLnggPCB4MSAmJiBwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueCA8IHgxKSB7XG4gICAgICAgICAgICAgICAgcDAgPSBuZXcgUG9pbnQoeDEsIHAwLnkgKyAocDEueSAtIHAwLnkpICogKCh4MSAtIHAwLngpIC8gKHAxLnggLSBwMC54KSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MSwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgxIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55IDwgeTEgJiYgcDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnkgPCB5MSkge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MSAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgcDEgPSBuZXcgUG9pbnQocDAueCArIChwMS54IC0gcDAueCkgKiAoKHkxIC0gcDAueSkgLyAocDEueSAtIHAwLnkpKSwgeTEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocDAueCA+PSB4MiAmJiBwMS54ID49IHgyKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMCA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAxLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55ID49IHkyICYmIHAxLnkgPj0geTIpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAxID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFjbGlwcGVkTGluZSB8fCAhcDAuZXF1YWxzKGNsaXBwZWRMaW5lW2NsaXBwZWRMaW5lLmxlbmd0aCAtIDFdKSkge1xuICAgICAgICAgICAgICAgIGNsaXBwZWRMaW5lID0gW3AwXTtcbiAgICAgICAgICAgICAgICBjbGlwcGVkTGluZXMucHVzaChjbGlwcGVkTGluZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNsaXBwZWRMaW5lLnB1c2gocDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWRMaW5lcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3g7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveChhbmNob3IsIHgxLCB5MSwgeDIsIHkyLCBtYXhTY2FsZSkge1xuICAgIC8vIHRoZSBib3ggaXMgY2VudGVyZWQgYXJvdW5kIHRoZSBhbmNob3IgcG9pbnRcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcblxuICAgIC8vIGRpc3RhbmNlcyB0byB0aGUgZWRnZXMgZnJvbSB0aGUgYW5jaG9yXG4gICAgdGhpcy54MSA9IHgxO1xuICAgIHRoaXMueTEgPSB5MTtcbiAgICB0aGlzLngyID0geDI7XG4gICAgdGhpcy55MiA9IHkyO1xuXG4gICAgLy8gdGhlIGJveCBpcyBvbmx5IHZhbGlkIGZvciBzY2FsZXMgPCBtYXhTY2FsZS5cbiAgICAvLyBUaGUgYm94IGRvZXMgbm90IGJsb2NrIG90aGVyIGJveGVzIGF0IHNjYWxlcyA+PSBtYXhTY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG5cbiAgICAvLyB0aGUgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIGNhbiBmaXJzdCBiZSBzaG93blxuICAgIHRoaXMucGxhY2VtZW50U2NhbGUgPSAwO1xuXG4gICAgLy8gcm90YXRlZCBhbmQgc2NhbGVkIGJib3ggdXNlZCBmb3IgaW5kZXhpbmdcbiAgICB0aGlzWzBdID0gdGhpc1sxXSA9IHRoaXNbMl0gPSB0aGlzWzNdID0gMDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbGxpc2lvbkJveCA9IHJlcXVpcmUoJy4vY29sbGlzaW9uX2JveCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxpc2lvbkZlYXR1cmU7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkZlYXR1cmUobGluZSwgYW5jaG9yLCBzaGFwZWQsIGJveFNjYWxlLCBwYWRkaW5nLCBhbGlnbkxpbmUpIHtcblxuICAgIHZhciB5MSA9IHNoYXBlZC50b3AgKiBib3hTY2FsZSAtIHBhZGRpbmc7XG4gICAgdmFyIHkyID0gc2hhcGVkLmJvdHRvbSAqIGJveFNjYWxlICsgcGFkZGluZztcbiAgICB2YXIgeDEgPSBzaGFwZWQubGVmdCAqIGJveFNjYWxlIC0gcGFkZGluZztcbiAgICB2YXIgeDIgPSBzaGFwZWQucmlnaHQgKiBib3hTY2FsZSArIHBhZGRpbmc7XG5cbiAgICB0aGlzLmJveGVzID0gW107XG5cbiAgICBpZiAoYWxpZ25MaW5lKSB7XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IHkyIC0geTE7XG4gICAgICAgIHZhciBsZW5ndGggPSB4MiAtIHgxO1xuXG4gICAgICAgIGlmIChoZWlnaHQgPD0gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIHNldCBtaW5pbXVtIGJveCBoZWlnaHQgdG8gYXZvaWQgdmVyeSBtYW55IHNtYWxsIGxhYmVsc1xuICAgICAgICBoZWlnaHQgPSBNYXRoLm1heCgxMCAqIGJveFNjYWxlLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuYmJveGlmeUxhYmVsKGxpbmUsIGFuY2hvciwgbGVuZ3RoLCBoZWlnaHQpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ib3hlcy5wdXNoKG5ldyBDb2xsaXNpb25Cb3goYW5jaG9yLCB4MSwgeTEsIHgyLCB5MiwgSW5maW5pdHkpKTtcbiAgICB9XG59XG5cbkNvbGxpc2lvbkZlYXR1cmUucHJvdG90eXBlLmJib3hpZnlMYWJlbCA9IGZ1bmN0aW9uKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIGJveFNpemUpIHtcbiAgICB2YXIgc3RlcCA9IGJveFNpemUgLyAyO1xuICAgIHZhciBuQm94ZXMgPSBNYXRoLmZsb29yKGxhYmVsTGVuZ3RoIC8gc3RlcCk7XG5cbiAgICAvLyBvZmZzZXQgdGhlIGNlbnRlciBvZiB0aGUgZmlyc3QgYm94IGJ5IGhhbGYgYSBib3ggc28gdGhhdCB0aGUgZWRnZSBvZiB0aGVcbiAgICAvLyBib3ggaXMgYXQgdGhlIGVkZ2Ugb2YgdGhlIGxhYmVsLlxuICAgIHZhciBmaXJzdEJveE9mZnNldCA9IC1ib3hTaXplIC8gMjtcblxuICAgIHZhciBiYm94ZXMgPSB0aGlzLmJveGVzO1xuXG4gICAgdmFyIHAgPSBhbmNob3I7XG4gICAgdmFyIGluZGV4ID0gYW5jaG9yLnNlZ21lbnQgKyAxO1xuICAgIHZhciBhbmNob3JEaXN0YW5jZSA9IGZpcnN0Qm94T2Zmc2V0O1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICBkbyB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIC8vIGNoZWNrTWF4QW5nbGUgc2hvdWxkIGhhdmUgYWxyZWFkeSBjYXVnaHQgdGhpc1xuICAgICAgICBpZiAoaW5kZXggPCAwKSByZXR1cm4gYmJveGVzO1xuXG4gICAgICAgIGFuY2hvckRpc3RhbmNlIC09IGxpbmVbaW5kZXhdLmRpc3QocCk7XG4gICAgICAgIHAgPSBsaW5lW2luZGV4XTtcbiAgICB9IHdoaWxlIChhbmNob3JEaXN0YW5jZSA+IC1sYWJlbExlbmd0aCAvIDIpO1xuXG4gICAgdmFyIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5Cb3hlczsgaSsrKSB7XG4gICAgICAgIC8vIHRoZSBkaXN0YW5jZSB0aGUgYm94IHdpbGwgYmUgZnJvbSB0aGUgYW5jaG9yXG4gICAgICAgIHZhciBib3hEaXN0YW5jZVRvQW5jaG9yID0gLWxhYmVsTGVuZ3RoIC8gMiArIGkgKiBzdGVwO1xuXG4gICAgICAgIC8vIHRoZSBib3ggaXMgbm90IG9uIHRoZSBjdXJyZW50IHNlZ21lbnQuIE1vdmUgdG8gdGhlIG5leHQgc2VnbWVudC5cbiAgICAgICAgd2hpbGUgKGFuY2hvckRpc3RhbmNlICsgc2VnbWVudExlbmd0aCA8IGJveERpc3RhbmNlVG9BbmNob3IpIHtcbiAgICAgICAgICAgIGFuY2hvckRpc3RhbmNlICs9IHNlZ21lbnRMZW5ndGg7XG4gICAgICAgICAgICBpbmRleCsrO1xuXG4gICAgICAgICAgICAvLyBUaGVyZSBpc24ndCBlbm91Z2ggcm9vbSBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgbGluZS5cbiAgICAgICAgICAgIGlmIChpbmRleCArIDEgPj0gbGluZS5sZW5ndGgpIHJldHVybiBiYm94ZXM7XG5cbiAgICAgICAgICAgIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgZGlzdGFuY2UgdGhlIGJveCB3aWxsIGJlIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc2VnbWVudFxuICAgICAgICB2YXIgc2VnbWVudEJveERpc3RhbmNlID0gYm94RGlzdGFuY2VUb0FuY2hvciAtIGFuY2hvckRpc3RhbmNlO1xuXG4gICAgICAgIHZhciBwMCA9IGxpbmVbaW5kZXhdO1xuICAgICAgICB2YXIgcDEgPSBsaW5lW2luZGV4ICsgMV07XG4gICAgICAgIHZhciBib3hBbmNob3IgPSBwMS5zdWIocDApLl91bml0KCkuX211bHQoc2VnbWVudEJveERpc3RhbmNlKS5fYWRkKHAwKTtcblxuICAgICAgICB2YXIgZGlzdGFuY2VUb0lubmVyRWRnZSA9IE1hdGgubWF4KE1hdGguYWJzKGJveERpc3RhbmNlVG9BbmNob3IgLSBmaXJzdEJveE9mZnNldCkgLSBzdGVwIC8gMiwgMCk7XG4gICAgICAgIHZhciBtYXhTY2FsZSA9IGxhYmVsTGVuZ3RoIC8gMiAvIGRpc3RhbmNlVG9Jbm5lckVkZ2U7XG5cbiAgICAgICAgYmJveGVzLnB1c2gobmV3IENvbGxpc2lvbkJveChib3hBbmNob3IsIC1ib3hTaXplIC8gMiwgLWJveFNpemUgLyAyLCBib3hTaXplIC8gMiwgYm94U2l6ZSAvIDIsIG1heFNjYWxlKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJib3hlcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByYnVzaCA9IHJlcXVpcmUoJ3JidXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sbGlzaW9uVGlsZTtcblxuZnVuY3Rpb24gQ29sbGlzaW9uVGlsZSh6b29tLCB0aWxlRXh0ZW50LCB0aWxlU2l6ZSkge1xuICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgdGhpcy50aWxlUGl4ZWxSYXRpbyA9IHRpbGVFeHRlbnQgLyB0aWxlU2l6ZTtcbn1cblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWluU2NhbGUgPSAwLjI1O1xuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWF4U2NhbGUgPSAyO1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCkge1xuICAgIHRoaXMudHJlZSA9IHJidXNoKCk7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHRoaXMucm90YXRpb25NYXRyaXggPSBbY29zLCAtc2luLCBzaW4sIGNvc107XG5cbiAgICAvLyBTdHJldGNoIGJveGVzIGluIHkgZGlyZWN0aW9uIHRvIGFjY291bnQgZm9yIHRoZSBtYXAgdGlsdC5cbiAgICB0aGlzLnlTdHJldGNoID0gMSAvIE1hdGguY29zKHBpdGNoIC8gMTgwICogTWF0aC5QSSk7XG5cbiAgICAvLyBUaGUgYW1vdW50IHRoZSBtYXAgaXMgc3F1aXNoZWQgZGVwZW5kcyBvbiB0aGUgeSBwb3NpdGlvbi5cbiAgICAvLyBTb3J0IG9mIGFjY291bnQgZm9yIHRoaXMgYnkgbWFraW5nIGFsbCBib3hlcyBhIGJpdCBiaWdnZXIuXG4gICAgdGhpcy55U3RyZXRjaCA9IE1hdGgucG93KHRoaXMueVN0cmV0Y2gsIDEuMyk7XG59O1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5wbGFjZUZlYXR1cmUgPSBmdW5jdGlvbihmZWF0dXJlKSB7XG5cbiAgICB2YXIgbWluUGxhY2VtZW50U2NhbGUgPSB0aGlzLm1pblNjYWxlO1xuICAgIHZhciByb3RhdGlvbk1hdHJpeCA9IHRoaXMucm90YXRpb25NYXRyaXg7XG4gICAgdmFyIHlTdHJldGNoID0gdGhpcy55U3RyZXRjaDtcblxuICAgIGZvciAodmFyIGIgPSAwOyBiIDwgZmVhdHVyZS5ib3hlcy5sZW5ndGg7IGIrKykge1xuXG4gICAgICAgIHZhciBib3ggPSBmZWF0dXJlLmJveGVzW2JdO1xuXG4gICAgICAgIHZhciBhbmNob3IgPSBib3guYW5jaG9yLm1hdE11bHQocm90YXRpb25NYXRyaXgpO1xuICAgICAgICB2YXIgeCA9IGFuY2hvci54O1xuICAgICAgICB2YXIgeSA9IGFuY2hvci55O1xuXG4gICAgICAgIGJveFswXSA9IHggKyBib3gueDE7XG4gICAgICAgIGJveFsxXSA9IHkgKyBib3gueTEgKiB5U3RyZXRjaDtcbiAgICAgICAgYm94WzJdID0geCArIGJveC54MjtcbiAgICAgICAgYm94WzNdID0geSArIGJveC55MiAqIHlTdHJldGNoO1xuXG4gICAgICAgIHZhciBibG9ja2luZ0JveGVzID0gdGhpcy50cmVlLnNlYXJjaChib3gpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tpbmdCb3hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJsb2NraW5nID0gYmxvY2tpbmdCb3hlc1tpXTtcbiAgICAgICAgICAgIHZhciBibG9ja2luZ0FuY2hvciA9IGJsb2NraW5nLmFuY2hvci5tYXRNdWx0KHJvdGF0aW9uTWF0cml4KTtcblxuICAgICAgICAgICAgLy8gRmluZCB0aGUgbG93ZXN0IHNjYWxlIGF0IHdoaWNoIHRoZSB0d28gYm94ZXMgY2FuIGZpdCBzaWRlIGJ5IHNpZGUgd2l0aG91dCBvdmVybGFwcGluZy5cbiAgICAgICAgICAgIC8vIE9yaWdpbmFsIGFsZ29yaXRobTpcbiAgICAgICAgICAgIHZhciBzMSA9IChibG9ja2luZy54MSAtIGJveC54MikgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSBsZWZ0IG9mIG9sZCBib3hcbiAgICAgICAgICAgIHZhciBzMiA9IChibG9ja2luZy54MiAtIGJveC54MSkgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSByaWdodCBvZiBvbGQgYm94XG4gICAgICAgICAgICB2YXIgczMgPSAoYmxvY2tpbmcueTEgLSBib3gueTIpICogeVN0cmV0Y2ggLyAoeSAtIGJsb2NraW5nQW5jaG9yLnkpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSB0b3Agb2Ygb2xkIGJveFxuICAgICAgICAgICAgdmFyIHM0ID0gKGJsb2NraW5nLnkyIC0gYm94LnkxKSAqIHlTdHJldGNoIC8gKHkgLSBibG9ja2luZ0FuY2hvci55KTsgLy8gc2NhbGUgYXQgd2hpY2ggbmV3IGJveCBpcyB0byB0aGUgYm90dG9tIG9mIG9sZCBib3hcblxuICAgICAgICAgICAgaWYgKGlzTmFOKHMxKSB8fCBpc05hTihzMikpIHMxID0gczIgPSAxO1xuICAgICAgICAgICAgaWYgKGlzTmFOKHMzKSB8fCBpc05hTihzNCkpIHMzID0gczQgPSAxO1xuXG4gICAgICAgICAgICB2YXIgY29sbGlzaW9uRnJlZVNjYWxlID0gTWF0aC5taW4oTWF0aC5tYXgoczEsIHMyKSwgTWF0aC5tYXgoczMsIHM0KSk7XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBibG9ja2luZy5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIEFmdGVyIGEgYm94J3MgbWF4U2NhbGUgdGhlIGxhYmVsIGhhcyBzaHJ1bmsgZW5vdWdoIHRoYXQgdGhlIGJveCBpcyBubyBsb25nZXIgbmVlZGVkIHRvIGNvdmVyIGl0LFxuICAgICAgICAgICAgICAgIC8vIHNvIHVuYmxvY2sgdGhlIG5ldyBib3ggYXQgdGhlIHNjYWxlIHRoYXQgdGhlIG9sZCBib3ggZGlzYXBwZWFycy5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBibG9ja2luZy5tYXhTY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbGxpc2lvbkZyZWVTY2FsZSA+IGJveC5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBib3ggY2FuIG9ubHkgYmUgc2hvd24gYWZ0ZXIgaXQgaXMgdmlzaWJsZSwgdGhlbiB0aGUgYm94IGNhbiBuZXZlciBiZSBzaG93bi5cbiAgICAgICAgICAgICAgICAvLyBCdXQgdGhlIGxhYmVsIGNhbiBiZSBzaG93biBhZnRlciB0aGlzIGJveCBpcyBub3QgdmlzaWJsZS5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBib3gubWF4U2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBtaW5QbGFjZW1lbnRTY2FsZSAmJlxuICAgICAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPj0gYmxvY2tpbmcucGxhY2VtZW50U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGNvbGxpc2lvbiBvY2N1cnMgYXQgYSBsb3dlciBzY2FsZSB0aGFuIHByZXZpb3VzbHkgZm91bmQgY29sbGlzaW9uc1xuICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgY29sbGlzaW9uIG9jY3VycyB3aGlsZSB0aGUgb3RoZXIgbGFiZWwgaXMgdmlzaWJsZVxuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB0aGlzIGlzIHRoZSBsb3dlc3Qgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIHdvbid0IGNvbGxpZGUgd2l0aCBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIG1pblBsYWNlbWVudFNjYWxlID0gY29sbGlzaW9uRnJlZVNjYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPj0gdGhpcy5tYXhTY2FsZSkgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xufTtcblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUuaW5zZXJ0RmVhdHVyZSA9IGZ1bmN0aW9uKGZlYXR1cmUsIG1pblBsYWNlbWVudFNjYWxlKSB7XG5cbiAgICB2YXIgYm94ZXMgPSBmZWF0dXJlLmJveGVzO1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYm94ZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgYm94ZXNba10ucGxhY2VtZW50U2NhbGUgPSBtaW5QbGFjZW1lbnRTY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPCB0aGlzLm1heFNjYWxlKSB7XG4gICAgICAgIHRoaXMudHJlZS5sb2FkKGJveGVzKTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW50ZXJwb2xhdGUgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyk7XG52YXIgQW5jaG9yID0gcmVxdWlyZSgnLi4vc3ltYm9sL2FuY2hvcicpO1xudmFyIGNoZWNrTWF4QW5nbGUgPSByZXF1aXJlKCcuL2NoZWNrX21heF9hbmdsZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEFuY2hvcnM7XG5cbmZ1bmN0aW9uIGdldEFuY2hvcnMobGluZSwgc3BhY2luZywgbWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgYm94U2NhbGUsIG92ZXJzY2FsaW5nKSB7XG5cbiAgICAvLyBSZXNhbXBsZSBhIGxpbmUgdG8gZ2V0IGFuY2hvciBwb2ludHMgZm9yIGxhYmVscyBhbmQgY2hlY2sgdGhhdCBlYWNoXG4gICAgLy8gcG90ZW50aWFsIGxhYmVsIHBhc3NlcyB0ZXh0LW1heC1hbmdsZSBjaGVjayBhbmQgaGFzIGVub3VnaCBmcm9vbSB0byBmaXRcbiAgICAvLyBvbiB0aGUgbGluZS5cblxuICAgIHZhciBhbmdsZVdpbmRvd1NpemUgPSBzaGFwZWRUZXh0ID9cbiAgICAgICAgMyAvIDUgKiBnbHlwaFNpemUgKiBib3hTY2FsZSA6XG4gICAgICAgIDA7XG5cbiAgICAvLyBPZmZzZXQgdGhlIGZpcnN0IGFuY2hvciBieSBoYWxmIHRoZSBsYWJlbCBsZW5ndGggKG9yIGhhbGYgdGhlIHNwYWNpbmcgZGlzdGFuY2UgZm9yIGljb25zKS5cbiAgICAvLyBBZGQgYSBiaXQgb2YgZXh0cmEgb2Zmc2V0IHRvIGF2b2lkIGNvbGxpc2lvbnMgYXQgVCBpbnRlcnNlY3Rpb25zLlxuICAgIHZhciBsYWJlbExlbmd0aCA9IHNoYXBlZFRleHQgPyBzaGFwZWRUZXh0LnJpZ2h0IC0gc2hhcGVkVGV4dC5sZWZ0IDogc3BhY2luZztcbiAgICB2YXIgZXh0cmFPZmZzZXQgPSBnbHlwaFNpemUgKiAyO1xuICAgIHZhciBvZmZzZXQgPSAoKGxhYmVsTGVuZ3RoIC8gMiArIGV4dHJhT2Zmc2V0KSAqIGJveFNjYWxlICogb3ZlcnNjYWxpbmcpICUgc3BhY2luZztcblxuICAgIHJldHVybiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoICogYm94U2NhbGUsIGZhbHNlKTtcbn1cblxuXG5mdW5jdGlvbiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoLCBwbGFjZUF0TWlkZGxlKSB7XG5cbiAgICB2YXIgZGlzdGFuY2UgPSAwLFxuICAgICAgICBtYXJrZWREaXN0YW5jZSA9IG9mZnNldCA/IG9mZnNldCAtIHNwYWNpbmcgOiAwO1xuXG4gICAgdmFyIGFuY2hvcnMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZS5sZW5ndGggLSAxOyBpKyspIHtcblxuICAgICAgICB2YXIgYSA9IGxpbmVbaV0sXG4gICAgICAgICAgICBiID0gbGluZVtpICsgMV07XG5cbiAgICAgICAgdmFyIHNlZ21lbnREaXN0ID0gYS5kaXN0KGIpLFxuICAgICAgICAgICAgYW5nbGUgPSBiLmFuZ2xlVG8oYSk7XG5cbiAgICAgICAgd2hpbGUgKG1hcmtlZERpc3RhbmNlICsgc3BhY2luZyA8IGRpc3RhbmNlICsgc2VnbWVudERpc3QpIHtcbiAgICAgICAgICAgIG1hcmtlZERpc3RhbmNlICs9IHNwYWNpbmc7XG5cbiAgICAgICAgICAgIHZhciB0ID0gKG1hcmtlZERpc3RhbmNlIC0gZGlzdGFuY2UpIC8gc2VnbWVudERpc3QsXG4gICAgICAgICAgICAgICAgeCA9IGludGVycG9sYXRlKGEueCwgYi54LCB0KSxcbiAgICAgICAgICAgICAgICB5ID0gaW50ZXJwb2xhdGUoYS55LCBiLnksIHQpO1xuXG4gICAgICAgICAgICBpZiAoeCA+PSAwICYmIHggPCA0MDk2ICYmIHkgPj0gMCAmJiB5IDwgNDA5Nikge1xuICAgICAgICAgICAgICAgIHggPSBNYXRoLnJvdW5kKHgpO1xuICAgICAgICAgICAgICAgIHkgPSBNYXRoLnJvdW5kKHkpO1xuICAgICAgICAgICAgICAgIHZhciBhbmNob3IgPSBuZXcgQW5jaG9yKHgsIHksIGFuZ2xlLCBpKTtcblxuICAgICAgICAgICAgICAgIGlmICghYW5nbGVXaW5kb3dTaXplIHx8IGNoZWNrTWF4QW5nbGUobGluZSwgYW5jaG9yLCBsYWJlbExlbmd0aCwgYW5nbGVXaW5kb3dTaXplLCBtYXhBbmdsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9ycy5wdXNoKGFuY2hvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGlzdGFuY2UgKz0gc2VnbWVudERpc3Q7XG4gICAgfVxuXG4gICAgaWYgKCFwbGFjZUF0TWlkZGxlICYmICFhbmNob3JzLmxlbmd0aCkge1xuICAgICAgICAvLyBUaGUgZmlyc3QgYXR0ZW1wdCBhdCBmaW5kaW5nIGFuY2hvcnMgYXQgd2hpY2ggbGFiZWxzIGNhbiBiZSBwbGFjZWQgZmFpbGVkLlxuICAgICAgICAvLyBUcnkgYWdhaW4sIGJ1dCB0aGlzIHRpbWUganVzdCB0cnkgcGxhY2luZyBvbmUgYW5jaG9yIGF0IHRoZSBtaWRkbGUgb2YgdGhlIGxpbmUuXG4gICAgICAgIC8vIFRoaXMgaGFzIHRoZSBtb3N0IGVmZmVjdCBmb3Igc2hvcnQgbGluZXMgaW4gb3ZlcnNjYWxlZCB0aWxlcywgc2luY2UgdGhlXG4gICAgICAgIC8vIGluaXRpYWwgb2Zmc2V0IHVzZWQgaW4gb3ZlcnNjYWxlZCB0aWxlcyBpcyBjYWxjdWxhdGVkIHRvIGFsaWduIGxhYmVscyB3aXRoIHBvc2l0aW9ucyBpblxuICAgICAgICAvLyBwYXJlbnQgdGlsZXMgaW5zdGVhZCBvZiBwbGFjaW5nIHRoZSBsYWJlbCBhcyBjbG9zZSB0byB0aGUgYmVnaW5uaW5nIGFzIHBvc3NpYmxlLlxuICAgICAgICBhbmNob3JzID0gcmVzYW1wbGUobGluZSwgZGlzdGFuY2UgLyAyLCBzcGFjaW5nLCBhbmdsZVdpbmRvd1NpemUsIG1heEFuZ2xlLCBsYWJlbExlbmd0aCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuY2hvcnM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCaW5QYWNrID0gcmVxdWlyZSgnLi9iaW5fcGFjaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoQXRsYXM7XG5mdW5jdGlvbiBHbHlwaEF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW5kZXggPSB7fTtcbiAgICB0aGlzLmlkcyA9IHt9O1xuICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbn1cblxuR2x5cGhBdGxhcy5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGRlYnVnKCkge1xuICAgICAgICByZXR1cm4gJ2NhbnZhcycgaW4gdGhpcztcbiAgICB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgJiYgIXRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuZ2V0R2x5cGhzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdseXBocyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghZ2x5cGhzW25hbWVdKSBnbHlwaHNbbmFtZV0gPSBbXTtcbiAgICAgICAgZ2x5cGhzW25hbWVdLnB1c2goaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBnbHlwaHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5nZXRSZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWN0cyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghcmVjdHNbbmFtZV0pIHJlY3RzW25hbWVdID0ge307XG4gICAgICAgIHJlY3RzW25hbWVdW2lkXSA9IHRoaXMuaW5kZXhba2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5yZW1vdmVHbHlwaHMgPSBmdW5jdGlvbihpZCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmlkcykge1xuXG4gICAgICAgIHZhciBpZHMgPSB0aGlzLmlkc1trZXldO1xuXG4gICAgICAgIHZhciBwb3MgPSBpZHMuaW5kZXhPZihpZCk7XG4gICAgICAgIGlmIChwb3MgPj0gMCkgaWRzLnNwbGljZShwb3MsIDEpO1xuICAgICAgICB0aGlzLmlkc1trZXldID0gaWRzO1xuXG4gICAgICAgIGlmICghaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHJlY3QgPSB0aGlzLmluZGV4W2tleV07XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHJlY3QuaDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5KSArIHJlY3QueDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHJlY3QudzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmJpbi5yZWxlYXNlKHJlY3QpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pbmRleFtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWRzW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHRoaXMudXBkYXRlVGV4dHVyZSh0aGlzLmdsKTtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmFkZEdseXBoID0gZnVuY3Rpb24oaWQsIG5hbWUsIGdseXBoLCBidWZmZXIpIHtcbiAgICBpZiAoIWdseXBoKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignbWlzc2luZyBnbHlwaCcsIGNvZGUsIFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIGtleSA9IG5hbWUgKyBcIiNcIiArIGdseXBoLmlkO1xuXG4gICAgLy8gVGhlIGdseXBoIGlzIGFscmVhZHkgaW4gdGhpcyB0ZXh0dXJlLlxuICAgIGlmICh0aGlzLmluZGV4W2tleV0pIHtcbiAgICAgICAgaWYgKHRoaXMuaWRzW2tleV0uaW5kZXhPZihpZCkgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmlkc1trZXldLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZGV4W2tleV07XG4gICAgfVxuXG4gICAgLy8gVGhlIGdseXBoIGJpdG1hcCBoYXMgemVybyB3aWR0aC5cbiAgICBpZiAoIWdseXBoLmJpdG1hcCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYnVmZmVyZWRXaWR0aCA9IGdseXBoLndpZHRoICsgYnVmZmVyICogMjtcbiAgICB2YXIgYnVmZmVyZWRIZWlnaHQgPSBnbHlwaC5oZWlnaHQgKyBidWZmZXIgKiAyO1xuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuICAgIHZhciBwYWNrV2lkdGggPSBidWZmZXJlZFdpZHRoICsgMiAqIHBhZGRpbmc7XG4gICAgdmFyIHBhY2tIZWlnaHQgPSBidWZmZXJlZEhlaWdodCArIDIgKiBwYWRkaW5nO1xuXG4gICAgLy8gSW5jcmVhc2UgdG8gbmV4dCBudW1iZXIgZGl2aXNpYmxlIGJ5IDQsIGJ1dCBhdCBsZWFzdCAxLlxuICAgIC8vIFRoaXMgaXMgc28gd2UgY2FuIHNjYWxlIGRvd24gdGhlIHRleHR1cmUgY29vcmRpbmF0ZXMgYW5kIHBhY2sgdGhlbVxuICAgIC8vIGludG8gMiBieXRlcyByYXRoZXIgdGhhbiA0IGJ5dGVzLlxuICAgIHBhY2tXaWR0aCArPSAoNCAtIHBhY2tXaWR0aCAlIDQpO1xuICAgIHBhY2tIZWlnaHQgKz0gKDQgLSBwYWNrSGVpZ2h0ICUgNCk7XG5cbiAgICB2YXIgcmVjdCA9IHRoaXMuYmluLmFsbG9jYXRlKHBhY2tXaWR0aCwgcGFja0hlaWdodCk7XG4gICAgaWYgKHJlY3QueCA8IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdnbHlwaCBiaXRtYXAgb3ZlcmZsb3cnKTtcbiAgICAgICAgcmV0dXJuIHsgZ2x5cGg6IGdseXBoLCByZWN0OiBudWxsIH07XG4gICAgfVxuXG4gICAgdGhpcy5pbmRleFtrZXldID0gcmVjdDtcbiAgICB0aGlzLmlkc1trZXldID0gW2lkXTtcblxuICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgdmFyIHNvdXJjZSA9IGdseXBoLmJpdG1hcDtcbiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGJ1ZmZlcmVkSGVpZ2h0OyB5KyspIHtcbiAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5ICsgcGFkZGluZykgKyByZWN0LnggKyBwYWRkaW5nO1xuICAgICAgICB2YXIgeTIgPSBidWZmZXJlZFdpZHRoICogeTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBidWZmZXJlZFdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gc291cmNlW3kyICsgeF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcblxuICAgIHJldHVybiByZWN0O1xufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgdGhpcy5nbCA9IGdsO1xuICAgIGlmICghdGhpcy50ZXh0dXJlKSB7XG4gICAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuQUxQSEEsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCAwLCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgIH1cbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLnVwZGF0ZVRleHR1cmUgPSBmdW5jdGlvbihnbCkge1xuICAgIHRoaXMuYmluZChnbCk7XG4gICAgaWYgKHRoaXMuZGlydHkpIHtcblxuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy5kYXRhKTtcblxuICAgICAgICAvLyBERUJVR1xuICAgICAgICBpZiAodGhpcy5jdHgpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gdGhpcy5jdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKywgaiArPSA0KSB7XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2pdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICAgICAgICAgIGRhdGEuZGF0YVtqICsgMV0gPSB0aGlzLmRhdGFbaV07XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2ogKyAyXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaiArIDNdID0gMjU1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54LCBmcmVlLnksIGZyZWUudywgZnJlZS5oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcblxuICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplR2x5cGhzVVJMO1xudmFyIGdldEFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4JykuZ2V0QXJyYXlCdWZmZXI7XG52YXIgR2x5cGhzID0gcmVxdWlyZSgnLi4vdXRpbC9nbHlwaHMnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoU291cmNlO1xuXG4vKipcbiAqIEEgZ2x5cGggc291cmNlIGhhcyBhIFVSTCBmcm9tIHdoaWNoIHRvIGxvYWQgbmV3IGdseXBocyBhbmQgb3ducyBhIEdseXBoQXRsYXNcbiAqIHRoYXQgc3RvcmVzIGN1cnJlbnRseS1sb2FkZWQgZ2x5cGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgZ2x5cGggdGVtcGxhdGUgdXJsXG4gKiBAcGFyYW0ge09iamVjdH0gZ2x5cGhBdGxhcyBnbHlwaCBhdGxhcyBvYmplY3RcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEdseXBoU291cmNlKHVybCwgZ2x5cGhBdGxhcykge1xuICAgIHRoaXMudXJsID0gdXJsICYmIG5vcm1hbGl6ZVVSTCh1cmwpO1xuICAgIHRoaXMuZ2x5cGhBdGxhcyA9IGdseXBoQXRsYXM7XG4gICAgdGhpcy5zdGFja3MgPSBbXTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcbn1cblxuR2x5cGhTb3VyY2UucHJvdG90eXBlLmdldFNpbXBsZUdseXBocyA9IGZ1bmN0aW9uKGZvbnRzdGFjaywgZ2x5cGhJRHMsIHVpZCwgY2FsbGJhY2spIHtcblxuICAgIGlmICh0aGlzLnN0YWNrc1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10gPSB7fTtcblxuICAgIHZhciBnbHlwaHMgPSB7fTtcblxuICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja107XG4gICAgdmFyIGdseXBoQXRsYXMgPSB0aGlzLmdseXBoQXRsYXM7XG5cbiAgICAvLyB0aGUgbnVtYmVyIG9mIHBpeGVscyB0aGUgc2RmIGJpdG1hcHMgYXJlIHBhZGRlZCBieVxuICAgIHZhciBidWZmZXIgPSAzO1xuXG4gICAgdmFyIG1pc3NpbmcgPSB7fTtcbiAgICB2YXIgcmVtYWluaW5nID0gMDtcbiAgICB2YXIgcmFuZ2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdseXBoSURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnbHlwaElEID0gZ2x5cGhJRHNbaV07XG4gICAgICAgIHJhbmdlID0gTWF0aC5mbG9vcihnbHlwaElEIC8gMjU2KTtcblxuICAgICAgICBpZiAoc3RhY2tbcmFuZ2VdKSB7XG4gICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFja1tyYW5nZV0uZ2x5cGhzW2dseXBoSURdO1xuICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICBpZiAoZ2x5cGgpIGdseXBoc1tnbHlwaElEXSA9IG5ldyBTaW1wbGVHbHlwaChnbHlwaCwgcmVjdCwgYnVmZmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nW3JhbmdlXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1tyYW5nZV0gPSBbXTtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pc3NpbmdbcmFuZ2VdLnB1c2goZ2x5cGhJRCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXJlbWFpbmluZykgY2FsbGJhY2sodW5kZWZpbmVkLCBnbHlwaHMpO1xuXG4gICAgdmFyIG9uUmFuZ2VMb2FkZWQgPSBmdW5jdGlvbihlcnIsIHJhbmdlLCBkYXRhKSB7XG4gICAgICAgIC8vIFRPRE8gbm90IGJlIHNpbGVudCBhYm91dCBlcnJvcnNcbiAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja11bcmFuZ2VdID0gZGF0YS5zdGFja3NbMF07XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdbcmFuZ2VdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdseXBoSUQgPSBtaXNzaW5nW3JhbmdlXVtpXTtcbiAgICAgICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFjay5nbHlwaHNbZ2x5cGhJRF07XG4gICAgICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKGdseXBoKSBnbHlwaHNbZ2x5cGhJRF0gPSBuZXcgU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIGdseXBocyk7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgZm9yICh2YXIgciBpbiBtaXNzaW5nKSB7XG4gICAgICAgIHRoaXMubG9hZFJhbmdlKGZvbnRzdGFjaywgciwgb25SYW5nZUxvYWRlZCk7XG4gICAgfVxufTtcblxuLy8gQSBzaW1wbGlmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnbHlwaCBjb250YWluaW5nIG9ubHkgdGhlIHByb3BlcnRpZXMgbmVlZGVkIGZvciBzaGFwaW5nLlxuZnVuY3Rpb24gU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcikge1xuICAgIHZhciBwYWRkaW5nID0gMTtcbiAgICB0aGlzLmFkdmFuY2UgPSBnbHlwaC5hZHZhbmNlO1xuICAgIHRoaXMubGVmdCA9IGdseXBoLmxlZnQgLSBidWZmZXIgLSBwYWRkaW5nO1xuICAgIHRoaXMudG9wID0gZ2x5cGgudG9wICsgYnVmZmVyICsgcGFkZGluZztcbiAgICB0aGlzLnJlY3QgPSByZWN0O1xufVxuXG5HbHlwaFNvdXJjZS5wcm90b3R5cGUubG9hZFJhbmdlID0gZnVuY3Rpb24oZm9udHN0YWNrLCByYW5nZSwgY2FsbGJhY2spIHtcblxuICAgIGlmIChyYW5nZSAqIDI1NiA+IDY1NTM1KSByZXR1cm4gY2FsbGJhY2soJ2d5cGhzID4gNjU1MzUgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgaWYgKHRoaXMubG9hZGluZ1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMubG9hZGluZ1tmb250c3RhY2tdID0ge307XG4gICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbZm9udHN0YWNrXTtcblxuICAgIGlmIChsb2FkaW5nW3JhbmdlXSkge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXSA9IFtjYWxsYmFja107XG5cbiAgICAgICAgdmFyIHJhbmdlTmFtZSA9IChyYW5nZSAqIDI1NikgKyAnLScgKyAocmFuZ2UgKiAyNTYgKyAyNTUpO1xuICAgICAgICB2YXIgdXJsID0gZ2x5cGhVcmwoZm9udHN0YWNrLCByYW5nZU5hbWUsIHRoaXMudXJsKTtcblxuICAgICAgICBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgdmFyIGdseXBocyA9ICFlcnIgJiYgbmV3IEdseXBocyhuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1tyYW5nZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2FkaW5nW3JhbmdlXVtpXShlcnIsIHJhbmdlLCBnbHlwaHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGxvYWRpbmdbcmFuZ2VdO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFVzZSBDTkFNRSBzaGFyZGluZyB0byBsb2FkIGEgc3BlY2lmaWMgZ2x5cGggcmFuZ2Ugb3ZlciBhIHJhbmRvbWl6ZWRcbiAqIGJ1dCBjb25zaXN0ZW50IHN1YmRvbWFpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250c3RhY2sgY29tbWEtam9pbmVkIGZvbnRzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmFuZ2UgY29tbWEtam9pbmVkIHJhbmdlXG4gKiBAcGFyYW0ge3VybH0gdXJsIHRlbXBsYXRlZCB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3ViZG9tYWlucz1hYmNdIHN1YmRvbWFpbnMgYXMgYSBzdHJpbmcgd2hlcmUgZWFjaCBsZXR0ZXIgaXMgb25lLlxuICogQHJldHVybnMge3N0cmluZ30gYSB1cmwgdG8gbG9hZCB0aGF0IHNlY3Rpb24gb2YgZ2x5cGhzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBnbHlwaFVybChmb250c3RhY2ssIHJhbmdlLCB1cmwsIHN1YmRvbWFpbnMpIHtcbiAgICBzdWJkb21haW5zID0gc3ViZG9tYWlucyB8fCAnYWJjJztcblxuICAgIHJldHVybiB1cmxcbiAgICAgICAgLnJlcGxhY2UoJ3tzfScsIHN1YmRvbWFpbnNbZm9udHN0YWNrLmxlbmd0aCAlIHN1YmRvbWFpbnMubGVuZ3RoXSlcbiAgICAgICAgLnJlcGxhY2UoJ3tmb250c3RhY2t9JywgZm9udHN0YWNrKVxuICAgICAgICAucmVwbGFjZSgne3JhbmdlfScsIHJhbmdlKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmVhdHVyZXMsIHRleHRGZWF0dXJlcywgZ2VvbWV0cmllcykge1xuXG4gICAgdmFyIGxlZnRJbmRleCA9IHt9LFxuICAgICAgICByaWdodEluZGV4ID0ge30sXG4gICAgICAgIG1lcmdlZEZlYXR1cmVzID0gW10sXG4gICAgICAgIG1lcmdlZEdlb20gPSBbXSxcbiAgICAgICAgbWVyZ2VkVGV4dHMgPSBbXSxcbiAgICAgICAgbWVyZ2VkSW5kZXggPSAwLFxuICAgICAgICBrO1xuXG4gICAgZnVuY3Rpb24gYWRkKGspIHtcbiAgICAgICAgbWVyZ2VkRmVhdHVyZXMucHVzaChmZWF0dXJlc1trXSk7XG4gICAgICAgIG1lcmdlZEdlb20ucHVzaChnZW9tZXRyaWVzW2tdKTtcbiAgICAgICAgbWVyZ2VkVGV4dHMucHVzaCh0ZXh0RmVhdHVyZXNba10pO1xuICAgICAgICBtZXJnZWRJbmRleCsrO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKSB7XG4gICAgICAgIHZhciBpID0gcmlnaHRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgZGVsZXRlIHJpZ2h0SW5kZXhbbGVmdEtleV07XG4gICAgICAgIHJpZ2h0SW5kZXhbcmlnaHRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnBvcCgpO1xuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdID0gbWVyZ2VkR2VvbVtpXVswXS5jb25jYXQoZ2VvbVswXSk7XG4gICAgICAgIHJldHVybiBpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbUxlZnQobGVmdEtleSwgcmlnaHRLZXksIGdlb20pIHtcbiAgICAgICAgdmFyIGkgPSBsZWZ0SW5kZXhbcmlnaHRLZXldO1xuICAgICAgICBkZWxldGUgbGVmdEluZGV4W3JpZ2h0S2V5XTtcbiAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnNoaWZ0KCk7XG4gICAgICAgIG1lcmdlZEdlb21baV1bMF0gPSBnZW9tWzBdLmNvbmNhdChtZXJnZWRHZW9tW2ldWzBdKTtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0S2V5KHRleHQsIGdlb20sIG9uUmlnaHQpIHtcbiAgICAgICAgdmFyIHBvaW50ID0gb25SaWdodCA/IGdlb21bMF1bZ2VvbVswXS5sZW5ndGggLSAxXSA6IGdlb21bMF1bMF07XG4gICAgICAgIHJldHVybiB0ZXh0ICsgJzonICsgcG9pbnQueCArICc6JyArIHBvaW50Lnk7XG4gICAgfVxuXG4gICAgZm9yIChrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBnZW9tID0gZ2VvbWV0cmllc1trXSxcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0RmVhdHVyZXNba107XG5cbiAgICAgICAgaWYgKCF0ZXh0KSB7XG4gICAgICAgICAgICBhZGQoayk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsZWZ0S2V5ID0gZ2V0S2V5KHRleHQsIGdlb20pLFxuICAgICAgICAgICAgcmlnaHRLZXkgPSBnZXRLZXkodGV4dCwgZ2VvbSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKChsZWZ0S2V5IGluIHJpZ2h0SW5kZXgpICYmIChyaWdodEtleSBpbiBsZWZ0SW5kZXgpICYmIChyaWdodEluZGV4W2xlZnRLZXldICE9PSBsZWZ0SW5kZXhbcmlnaHRLZXldKSkge1xuICAgICAgICAgICAgLy8gZm91bmQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IGFkamFjZW50IHRvIGJvdGggZW5kcyBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZSBhbGwgdGhyZWVcbiAgICAgICAgICAgIHZhciBqID0gbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG4gICAgICAgICAgICB2YXIgaSA9IG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBtZXJnZWRHZW9tW2pdKTtcblxuICAgICAgICAgICAgZGVsZXRlIGxlZnRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSByaWdodEluZGV4W3JpZ2h0S2V5XTtcblxuICAgICAgICAgICAgcmlnaHRJbmRleFtnZXRLZXkodGV4dCwgbWVyZ2VkR2VvbVtpXSwgdHJ1ZSldID0gaTtcbiAgICAgICAgICAgIG1lcmdlZEdlb21bal0gPSBudWxsO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobGVmdEtleSBpbiByaWdodEluZGV4KSB7XG4gICAgICAgICAgICAvLyBmb3VuZCBtZXJnZWFibGUgbGluZSBhZGphY2VudCB0byB0aGUgc3RhcnQgb2YgdGhlIGN1cnJlbnQgbGluZSwgbWVyZ2VcbiAgICAgICAgICAgIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHJpZ2h0S2V5IGluIGxlZnRJbmRleCkge1xuICAgICAgICAgICAgLy8gZm91bmQgbWVyZ2VhYmxlIGxpbmUgYWRqYWNlbnQgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZVxuICAgICAgICAgICAgbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vIGFkamFjZW50IGxpbmVzLCBhZGQgYXMgYSBuZXcgaXRlbVxuICAgICAgICAgICAgYWRkKGspO1xuICAgICAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gbWVyZ2VkSW5kZXggLSAxO1xuICAgICAgICAgICAgcmlnaHRJbmRleFtyaWdodEtleV0gPSBtZXJnZWRJbmRleCAtIDE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmZWF0dXJlczogbWVyZ2VkRmVhdHVyZXMsXG4gICAgICAgIHRleHRGZWF0dXJlczogbWVyZ2VkVGV4dHMsXG4gICAgICAgIGdlb21ldHJpZXM6IG1lcmdlZEdlb21cbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEljb25RdWFkczogZ2V0SWNvblF1YWRzLFxuICAgIGdldEdseXBoUXVhZHM6IGdldEdseXBoUXVhZHNcbn07XG5cbnZhciBtaW5TY2FsZSA9IDAuNTsgLy8gdW5kZXJzY2FsZSBieSAxIHpvb20gbGV2ZWxcblxuZnVuY3Rpb24gU3ltYm9sUXVhZChhbmNob3IsIHRsLCB0ciwgYmwsIGJyLCB0ZXgsIGFuZ2xlLCBtaW5TY2FsZSwgbWF4U2NhbGUpIHtcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcbiAgICB0aGlzLnRsID0gdGw7XG4gICAgdGhpcy50ciA9IHRyO1xuICAgIHRoaXMuYmwgPSBibDtcbiAgICB0aGlzLmJyID0gYnI7XG4gICAgdGhpcy50ZXggPSB0ZXg7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuICAgIHRoaXMubWluU2NhbGUgPSBtaW5TY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG59XG5cbmZ1bmN0aW9uIGdldEljb25RdWFkcyhhbmNob3IsIHNoYXBlZEljb24sIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHJlY3QgPSBzaGFwZWRJY29uLmltYWdlLnJlY3Q7XG5cbiAgICB2YXIgYm9yZGVyID0gMTtcbiAgICB2YXIgbGVmdCA9IHNoYXBlZEljb24ubGVmdCAtIGJvcmRlcjtcbiAgICB2YXIgcmlnaHQgPSBsZWZ0ICsgcmVjdC53O1xuICAgIHZhciB0b3AgPSBzaGFwZWRJY29uLnRvcCAtIGJvcmRlcjtcbiAgICB2YXIgYm90dG9tID0gdG9wICsgcmVjdC5oO1xuICAgIHZhciB0bCA9IG5ldyBQb2ludChsZWZ0LCB0b3ApO1xuICAgIHZhciB0ciA9IG5ldyBQb2ludChyaWdodCwgdG9wKTtcbiAgICB2YXIgYnIgPSBuZXcgUG9pbnQocmlnaHQsIGJvdHRvbSk7XG4gICAgdmFyIGJsID0gbmV3IFBvaW50KGxlZnQsIGJvdHRvbSk7XG5cbiAgICB2YXIgYW5nbGUgPSBsYXlvdXRbJ2ljb24tcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIGlmIChhbG9uZ0xpbmUpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2FuY2hvci5zZWdtZW50XTtcbiAgICAgICAgYW5nbGUgKz0gTWF0aC5hdGFuMihhbmNob3IueSAtIHByZXYueSwgYW5jaG9yLnggLSBwcmV2LngpO1xuICAgIH1cblxuICAgIGlmIChhbmdsZSkge1xuICAgICAgICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpLFxuICAgICAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpLFxuICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgIHRsID0gdGwubWF0TXVsdChtYXRyaXgpO1xuICAgICAgICB0ciA9IHRyLm1hdE11bHQobWF0cml4KTtcbiAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgIGJyID0gYnIubWF0TXVsdChtYXRyaXgpO1xuICAgIH1cblxuICAgIHJldHVybiBbbmV3IFN5bWJvbFF1YWQoYW5jaG9yLCB0bCwgdHIsIGJsLCBiciwgc2hhcGVkSWNvbi5pbWFnZS5yZWN0LCAwLCBtaW5TY2FsZSwgSW5maW5pdHkpXTtcbn1cblxuZnVuY3Rpb24gZ2V0R2x5cGhRdWFkcyhhbmNob3IsIHNoYXBpbmcsIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHRleHRSb3RhdGUgPSBsYXlvdXRbJ3RleHQtcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBrZWVwVXByaWdodCA9IGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXTtcblxuICAgIHZhciBwb3NpdGlvbmVkR2x5cGhzID0gc2hhcGluZy5wb3NpdGlvbmVkR2x5cGhzO1xuICAgIHZhciBxdWFkcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2tdO1xuICAgICAgICB2YXIgZ2x5cGggPSBwb3NpdGlvbmVkR2x5cGguZ2x5cGg7XG4gICAgICAgIHZhciByZWN0ID0gZ2x5cGgucmVjdDtcblxuICAgICAgICBpZiAoIXJlY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjZW50ZXJYID0gKHBvc2l0aW9uZWRHbHlwaC54ICsgZ2x5cGguYWR2YW5jZSAvIDIpICogYm94U2NhbGU7XG5cbiAgICAgICAgdmFyIGdseXBoSW5zdGFuY2VzO1xuICAgICAgICB2YXIgbGFiZWxNaW5TY2FsZSA9IG1pblNjYWxlO1xuICAgICAgICBpZiAoYWxvbmdMaW5lKSB7XG4gICAgICAgICAgICBnbHlwaEluc3RhbmNlcyA9IFtdO1xuICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIDEpO1xuICAgICAgICAgICAgaWYgKGtlZXBVcHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IE1hdGgubWluKGxhYmVsTWluU2NhbGUsIGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIC0xKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdseXBoSW5zdGFuY2VzID0gW3tcbiAgICAgICAgICAgICAgICBhbmNob3I6IGFuY2hvcixcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICAgICAgYW5nbGU6IDAsXG4gICAgICAgICAgICAgICAgbWF4U2NhbGU6IEluZmluaXR5LFxuICAgICAgICAgICAgICAgIG1pblNjYWxlOiBtaW5TY2FsZVxuICAgICAgICAgICAgfV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeDEgPSBwb3NpdGlvbmVkR2x5cGgueCArIGdseXBoLmxlZnQsXG4gICAgICAgICAgICB5MSA9IHBvc2l0aW9uZWRHbHlwaC55IC0gZ2x5cGgudG9wLFxuICAgICAgICAgICAgeDIgPSB4MSArIHJlY3QudyxcbiAgICAgICAgICAgIHkyID0geTEgKyByZWN0LmgsXG5cbiAgICAgICAgICAgIG90bCA9IG5ldyBQb2ludCh4MSwgeTEpLFxuICAgICAgICAgICAgb3RyID0gbmV3IFBvaW50KHgyLCB5MSksXG4gICAgICAgICAgICBvYmwgPSBuZXcgUG9pbnQoeDEsIHkyKSxcbiAgICAgICAgICAgIG9iciA9IG5ldyBQb2ludCh4MiwgeTIpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2x5cGhJbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gZ2x5cGhJbnN0YW5jZXNbaV0sXG4gICAgICAgICAgICAgICAgdGwgPSBvdGwsXG4gICAgICAgICAgICAgICAgdHIgPSBvdHIsXG4gICAgICAgICAgICAgICAgYmwgPSBvYmwsXG4gICAgICAgICAgICAgICAgYnIgPSBvYnIsXG4gICAgICAgICAgICAgICAgYW5nbGUgPSBpbnN0YW5jZS5hbmdsZSArIHRleHRSb3RhdGU7XG5cbiAgICAgICAgICAgIGlmIChhbmdsZSkge1xuICAgICAgICAgICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgICAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgdHIgPSB0ci5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgbGFiZWwgZnJvbSBleHRlbmRpbmcgcGFzdCB0aGUgZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICB2YXIgZ2x5cGhNaW5TY2FsZSA9IE1hdGgubWF4KGluc3RhbmNlLm1pblNjYWxlLCBsYWJlbE1pblNjYWxlKTtcblxuICAgICAgICAgICAgdmFyIGdseXBoQW5nbGUgPSAoYW5jaG9yLmFuZ2xlICsgdGV4dFJvdGF0ZSArIGluc3RhbmNlLm9mZnNldCArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG4gICAgICAgICAgICBxdWFkcy5wdXNoKG5ldyBTeW1ib2xRdWFkKGluc3RhbmNlLmFuY2hvciwgdGwsIHRyLCBibCwgYnIsIHJlY3QsIGdseXBoQW5nbGUsIGdseXBoTWluU2NhbGUsIGluc3RhbmNlLm1heFNjYWxlKSk7XG5cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBxdWFkcztcbn1cblxuZnVuY3Rpb24gZ2V0U2VnbWVudEdseXBocyhnbHlwaHMsIGFuY2hvciwgb2Zmc2V0LCBsaW5lLCBzZWdtZW50LCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgdXBzaWRlRG93biA9IGRpcmVjdGlvbiA8IDA7XG5cbiAgICBpZiAob2Zmc2V0IDwgMCkgZGlyZWN0aW9uICo9IC0xO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHNlZ21lbnQrKztcblxuICAgIHZhciBuZXdBbmNob3IgPSBhbmNob3I7XG4gICAgdmFyIGVuZCA9IGxpbmVbc2VnbWVudF07XG4gICAgdmFyIHByZXZTY2FsZSA9IEluZmluaXR5O1xuXG4gICAgb2Zmc2V0ID0gTWF0aC5hYnMob2Zmc2V0KTtcblxuICAgIHZhciBwbGFjZW1lbnRTY2FsZSA9IG1pblNjYWxlO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgdmFyIGRpc3RhbmNlID0gbmV3QW5jaG9yLmRpc3QoZW5kKTtcbiAgICAgICAgdmFyIHNjYWxlID0gb2Zmc2V0IC8gZGlzdGFuY2U7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBhbmdsZSBvZiB0aGUgbGluZSBzZWdtZW50XG4gICAgICAgIHZhciBhbmdsZSA9IE1hdGguYXRhbjIoZW5kLnkgLSBuZXdBbmNob3IueSwgZW5kLnggLSBuZXdBbmNob3IueCk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPCAwKSBhbmdsZSArPSBNYXRoLlBJO1xuICAgICAgICBpZiAodXBzaWRlRG93bikgYW5nbGUgKz0gTWF0aC5QSTtcblxuICAgICAgICBnbHlwaHMucHVzaCh7XG4gICAgICAgICAgICBhbmNob3I6IG5ldyBBbmNob3IobmV3QW5jaG9yLngsIG5ld0FuY2hvci55LCBhbmNob3IuYW5nbGUpLFxuICAgICAgICAgICAgb2Zmc2V0OiB1cHNpZGVEb3duID8gTWF0aC5QSSA6IDAsXG4gICAgICAgICAgICBtaW5TY2FsZTogc2NhbGUsXG4gICAgICAgICAgICBtYXhTY2FsZTogcHJldlNjYWxlLFxuICAgICAgICAgICAgYW5nbGU6IChhbmdsZSArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHNjYWxlIDw9IHBsYWNlbWVudFNjYWxlKSBicmVhaztcblxuICAgICAgICBuZXdBbmNob3IgPSBlbmQ7XG5cbiAgICAgICAgLy8gc2tpcCBkdXBsaWNhdGUgbm9kZXNcbiAgICAgICAgd2hpbGUgKG5ld0FuY2hvci5lcXVhbHMoZW5kKSkge1xuICAgICAgICAgICAgc2VnbWVudCArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICBlbmQgPSBsaW5lW3NlZ21lbnRdO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdW5pdCA9IGVuZC5zdWIobmV3QW5jaG9yKS5fdW5pdCgpO1xuICAgICAgICBuZXdBbmNob3IgPSBuZXdBbmNob3Iuc3ViKHVuaXQuX211bHQoZGlzdGFuY2UpKTtcblxuICAgICAgICBwcmV2U2NhbGUgPSBzY2FsZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2VtZW50U2NhbGU7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVJY29ucztcblxuLy8gRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGljb25zIG5lZWQgdG8gYmUgbG9hZGVkLlxuZnVuY3Rpb24gcmVzb2x2ZUljb25zKGZlYXR1cmVzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdmFyIGljb25zID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWydpY29uLWltYWdlJ10pO1xuICAgICAgICBpZiAoIXRleHQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChpY29ucy5pbmRleE9mKHRleHQpIDwgMCkge1xuICAgICAgICAgICAgaWNvbnMucHVzaCh0ZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpY29ucztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVzb2x2ZVRleHQ7XG5cbi8qKlxuICogRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGdseXBoIHJhbmdlcyBuZWVkIHRvIGJlIGxvYWRlZFxuICogYW5kIGFwcGx5IGFueSB0ZXh0IHByZXByb2Nlc3NpbmcuIFRoZSByZW1haW5pbmcgdXNlcnMgb2YgdGV4dCBzaG91bGRcbiAqIHVzZSB0aGUgYHRleHRGZWF0dXJlc2Aga2V5IHJldHVybmVkIGJ5IHRoaXMgZnVuY3Rpb24gcmF0aGVyIHRoYW4gYWNjZXNzaW5nXG4gKiBmZWF0dXJlIHRleHQgZGlyZWN0bHkuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZXNvbHZlVGV4dChmZWF0dXJlcywgbGF5b3V0UHJvcGVydGllcywgZ2x5cGhzKSB7XG4gICAgdmFyIHRleHRGZWF0dXJlcyA9IFtdO1xuICAgIHZhciBjb2RlcG9pbnRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZpZWxkJ10pO1xuICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgIHRleHRGZWF0dXJlc1tpXSA9IG51bGw7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0ID0gdGV4dC50b1N0cmluZygpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LXRyYW5zZm9ybSddO1xuICAgICAgICBpZiAodHJhbnNmb3JtID09PSAndXBwZXJjYXNlJykge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQudG9Mb2NhbGVVcHBlckNhc2UoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2Zvcm0gPT09ICdsb3dlcmNhc2UnKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpsID0gdGV4dC5sZW5ndGg7IGogPCBqbDsgaisrKSB7XG4gICAgICAgICAgICBjb2RlcG9pbnRzLnB1c2godGV4dC5jaGFyQ29kZUF0KGopKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIGluZGV4ZXMgb2YgZmVhdHVyZXMgd2l0aCB0ZXh0LlxuICAgICAgICB0ZXh0RmVhdHVyZXNbaV0gPSB0ZXh0O1xuICAgIH1cblxuICAgIC8vIGdldCBhIGxpc3Qgb2YgdW5pcXVlIGNvZGVwb2ludHMgd2UgYXJlIG1pc3NpbmdcbiAgICBjb2RlcG9pbnRzID0gdW5pcShjb2RlcG9pbnRzLCBnbHlwaHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dEZlYXR1cmVzOiB0ZXh0RmVhdHVyZXMsXG4gICAgICAgIGNvZGVwb2ludHM6IGNvZGVwb2ludHNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB1bmlxKGlkcywgYWxyZWFkeUhhdmUpIHtcbiAgICB2YXIgdSA9IFtdO1xuICAgIHZhciBsYXN0O1xuICAgIGlkcy5zb3J0KHNvcnROdW1iZXJzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaWRzW2ldICE9PSBsYXN0KSB7XG4gICAgICAgICAgICBsYXN0ID0gaWRzW2ldO1xuICAgICAgICAgICAgaWYgKCFhbHJlYWR5SGF2ZVtsYXN0XSkgdS5wdXNoKGlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHU7XG59XG5cbmZ1bmN0aW9uIHNvcnROdW1iZXJzKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNoYXBlVGV4dDogc2hhcGVUZXh0LFxuICAgIHNoYXBlSWNvbjogc2hhcGVJY29uXG59O1xuXG5cbi8vIFRoZSBwb3NpdGlvbiBvZiBhIGdseXBoIHJlbGF0aXZlIHRvIHRoZSB0ZXh0J3MgYW5jaG9yIHBvaW50LlxuZnVuY3Rpb24gUG9zaXRpb25lZEdseXBoKGNvZGVQb2ludCwgeCwgeSwgZ2x5cGgpIHtcbiAgICB0aGlzLmNvZGVQb2ludCA9IGNvZGVQb2ludDtcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG4gICAgdGhpcy5nbHlwaCA9IGdseXBoO1xufVxuXG4vLyBBIGNvbGxlY3Rpb24gb2YgcG9zaXRpb25lZCBnbHlwaHMgYW5kIHNvbWUgbWV0YWRhdGFcbmZ1bmN0aW9uIFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5wb3NpdGlvbmVkR2x5cGhzID0gcG9zaXRpb25lZEdseXBocztcbiAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICB0aGlzLmJvdHRvbSA9IGJvdHRvbTtcbiAgICB0aGlzLmxlZnQgPSBsZWZ0O1xuICAgIHRoaXMucmlnaHQgPSByaWdodDtcbn1cblxuZnVuY3Rpb24gc2hhcGVUZXh0KHRleHQsIGdseXBocywgbWF4V2lkdGgsIGxpbmVIZWlnaHQsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSwgc3BhY2luZywgdHJhbnNsYXRlKSB7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IFtdO1xuICAgIHZhciBzaGFwaW5nID0gbmV3IFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdHJhbnNsYXRlWzFdLCB0cmFuc2xhdGVbMV0sIHRyYW5zbGF0ZVswXSwgdHJhbnNsYXRlWzBdKTtcblxuICAgIC8vIHRoZSB5IG9mZnNldCAqc2hvdWxkKiBiZSBwYXJ0IG9mIHRoZSBmb250IG1ldGFkYXRhXG4gICAgdmFyIHlPZmZzZXQgPSAtMTc7XG5cbiAgICB2YXIgeCA9IHRyYW5zbGF0ZVswXTtcbiAgICB2YXIgeSA9IHRyYW5zbGF0ZVsxXSArIHlPZmZzZXQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNvZGVQb2ludCA9IHRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgdmFyIGdseXBoID0gZ2x5cGhzW2NvZGVQb2ludF07XG5cbiAgICAgICAgaWYgKCFnbHlwaCkgY29udGludWU7XG5cbiAgICAgICAgcG9zaXRpb25lZEdseXBocy5wdXNoKG5ldyBQb3NpdGlvbmVkR2x5cGgoY29kZVBvaW50LCB4LCB5LCBnbHlwaCkpO1xuICAgICAgICB4ICs9IGdseXBoLmFkdmFuY2UgKyBzcGFjaW5nO1xuICAgIH1cblxuICAgIGlmICghcG9zaXRpb25lZEdseXBocy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSk7XG5cbiAgICByZXR1cm4gc2hhcGluZztcbn1cblxudmFyIGJyZWFrYWJsZSA9IHsgMzI6IHRydWUgfTsgLy8gQ3VycmVudGx5IG9ubHkgYnJlYWtzIGF0IHJlZ3VsYXIgc3BhY2VzXG5cbmZ1bmN0aW9uIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSkge1xuICAgIHZhciBsYXN0U2FmZUJyZWFrID0gbnVsbDtcblxuICAgIHZhciBsZW5ndGhCZWZvcmVDdXJyZW50TGluZSA9IDA7XG4gICAgdmFyIGxpbmVTdGFydEluZGV4ID0gMDtcbiAgICB2YXIgbGluZSA9IDA7XG5cbiAgICB2YXIgbWF4TGluZUxlbmd0aCA9IDA7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IHNoYXBpbmcucG9zaXRpb25lZEdseXBocztcblxuICAgIGlmIChtYXhXaWR0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9uZWRHbHlwaHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2ldO1xuXG4gICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGgueCAtPSBsZW5ndGhCZWZvcmVDdXJyZW50TGluZTtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRHbHlwaC55ICs9IGxpbmVIZWlnaHQgKiBsaW5lO1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb25lZEdseXBoLnggPiBtYXhXaWR0aCAmJiBsYXN0U2FmZUJyZWFrICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGluZUxlbmd0aCA9IHBvc2l0aW9uZWRHbHlwaHNbbGFzdFNhZmVCcmVhayArIDFdLng7XG4gICAgICAgICAgICAgICAgbWF4TGluZUxlbmd0aCA9IE1hdGgubWF4KGxpbmVMZW5ndGgsIG1heExpbmVMZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IGxhc3RTYWZlQnJlYWsgKyAxOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGhzW2tdLnkgKz0gbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25lZEdseXBoc1trXS54IC09IGxpbmVMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGp1c3RpZnkpIHtcbiAgICAgICAgICAgICAgICAgICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgbGFzdFNhZmVCcmVhayAtIDEsIGp1c3RpZnkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxpbmVTdGFydEluZGV4ID0gbGFzdFNhZmVCcmVhayArIDE7XG4gICAgICAgICAgICAgICAgbGFzdFNhZmVCcmVhayA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGVuZ3RoQmVmb3JlQ3VycmVudExpbmUgKz0gbGluZUxlbmd0aDtcbiAgICAgICAgICAgICAgICBsaW5lKys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChicmVha2FibGVbcG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0pIHtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYXN0UG9zaXRpb25lZEdseXBoID0gcG9zaXRpb25lZEdseXBoc1twb3NpdGlvbmVkR2x5cGhzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBsYXN0TGluZUxlbmd0aCA9IGxhc3RQb3NpdGlvbmVkR2x5cGgueCArIGdseXBoc1tsYXN0UG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0uYWR2YW5jZTtcbiAgICBtYXhMaW5lTGVuZ3RoID0gTWF0aC5tYXgobWF4TGluZUxlbmd0aCwgbGFzdExpbmVMZW5ndGgpO1xuXG4gICAgdmFyIGhlaWdodCA9IChsaW5lICsgMSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgcG9zaXRpb25lZEdseXBocy5sZW5ndGggLSAxLCBqdXN0aWZ5KTtcbiAgICBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBib3VuZGluZyBib3hcbiAgICBzaGFwaW5nLnRvcCArPSAtdmVydGljYWxBbGlnbiAqIGhlaWdodDtcbiAgICBzaGFwaW5nLmJvdHRvbSA9IHNoYXBpbmcudG9wICsgaGVpZ2h0O1xuICAgIHNoYXBpbmcubGVmdCArPSAtaG9yaXpvbnRhbEFsaWduICogbWF4TGluZUxlbmd0aDtcbiAgICBzaGFwaW5nLnJpZ2h0ID0gc2hhcGluZy5sZWZ0ICsgbWF4TGluZUxlbmd0aDtcbn1cblxuZnVuY3Rpb24ganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBzdGFydCwgZW5kLCBqdXN0aWZ5KSB7XG4gICAgdmFyIGxhc3RBZHZhbmNlID0gZ2x5cGhzW3Bvc2l0aW9uZWRHbHlwaHNbZW5kXS5jb2RlUG9pbnRdLmFkdmFuY2U7XG4gICAgdmFyIGxpbmVJbmRlbnQgPSAocG9zaXRpb25lZEdseXBoc1tlbmRdLnggKyBsYXN0QWR2YW5jZSkgKiBqdXN0aWZ5O1xuXG4gICAgZm9yICh2YXIgaiA9IHN0YXJ0OyBqIDw9IGVuZDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCAtPSBsaW5lSW5kZW50O1xuICAgIH1cblxufVxuXG5mdW5jdGlvbiBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpIHtcbiAgICB2YXIgc2hpZnRYID0gKGp1c3RpZnkgLSBob3Jpem9udGFsQWxpZ24pICogbWF4TGluZUxlbmd0aDtcbiAgICB2YXIgc2hpZnRZID0gKC12ZXJ0aWNhbEFsaWduICogKGxpbmUgKyAxKSArIDAuNSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCArPSBzaGlmdFg7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueSArPSBzaGlmdFk7XG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIHNoYXBlSWNvbihpbWFnZSwgbGF5b3V0KSB7XG4gICAgaWYgKCFpbWFnZSB8fCAhaW1hZ2UucmVjdCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZHggPSBsYXlvdXRbJ2ljb24tb2Zmc2V0J11bMF07XG4gICAgdmFyIGR5ID0gbGF5b3V0WydpY29uLW9mZnNldCddWzFdO1xuICAgIHZhciB4MSA9IGR4IC0gaW1hZ2Uud2lkdGggLyAyO1xuICAgIHZhciB4MiA9IHgxICsgaW1hZ2Uud2lkdGg7XG4gICAgdmFyIHkxID0gZHkgLSBpbWFnZS5oZWlnaHQgLyAyO1xuICAgIHZhciB5MiA9IHkxICsgaW1hZ2UuaGVpZ2h0O1xuXG4gICAgcmV0dXJuIG5ldyBQb3NpdGlvbmVkSWNvbihpbWFnZSwgeTEsIHkyLCB4MSwgeDIpO1xufVxuXG5mdW5jdGlvbiBQb3NpdGlvbmVkSWNvbihpbWFnZSwgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgIHRoaXMudG9wID0gdG9wO1xuICAgIHRoaXMuYm90dG9tID0gYm90dG9tO1xuICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmluUGFjayA9IHJlcXVpcmUoJy4vYmluX3BhY2snKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTcHJpdGVBdGxhcztcbmZ1bmN0aW9uIFNwcml0ZUF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW1hZ2VzID0ge307XG4gICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0dXJlID0gMDsgLy8gV2ViR0wgSURcbiAgICB0aGlzLmZpbHRlciA9IDA7IC8vIFdlYkdMIElEXG4gICAgdGhpcy5waXhlbFJhdGlvID0gMTtcbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcbn1cblxuU3ByaXRlQXRsYXMucHJvdG90eXBlID0ge1xuICAgIGdldCBkZWJ1ZygpIHtcbiAgICAgICAgcmV0dXJuICdjYW52YXMnIGluIHRoaXM7XG4gICAgfSxcbiAgICBzZXQgZGVidWcodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKG5ld1JhdGlvKSB7XG4gICAgaWYgKHRoaXMucGl4ZWxSYXRpbyA9PT0gbmV3UmF0aW8pIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBvbGRSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbztcbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBuZXdSYXRpbztcblxuICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGggKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLmRhdGE7XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIG9sZFdpZHRoID0gdGhpcy53aWR0aCAqIG9sZFJhdGlvO1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBvbGRSYXRpbztcbiAgICAgICAgdmFyIG5ld1dpZHRoID0gdGhpcy53aWR0aCAqIG5ld1JhdGlvO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBuZXdSYXRpbztcblxuICAgICAgICAvLyBCYXNpYyBpbWFnZSBzY2FsaW5nLiBUT0RPOiBSZXBsYWNlIHRoaXMgd2l0aCBiZXR0ZXIgaW1hZ2Ugc2NhbGluZy5cbiAgICAgICAgdmFyIG5ld0ltYWdlID0gdGhpcy5kYXRhO1xuICAgICAgICB2YXIgb2xkSW1hZ2UgPSBvbGREYXRhO1xuXG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgbmV3SGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgIHZhciBvbGRZT2Zmc2V0ID0gTWF0aC5mbG9vcigoeSAqIG9sZEhlaWdodCkgLyBuZXdIZWlnaHQpICogb2xkV2lkdGg7XG4gICAgICAgICAgICB2YXIgbmV3WU9mZnNldCA9IHkgKiBuZXdXaWR0aDtcbiAgICAgICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgbmV3V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIHZhciBvbGRYID0gTWF0aC5mbG9vcigoeCAqIG9sZFdpZHRoKSAvIG5ld1dpZHRoKTtcbiAgICAgICAgICAgICAgICBuZXdJbWFnZVtuZXdZT2Zmc2V0ICsgeF0gPSBvbGRJbWFnZVtvbGRZT2Zmc2V0ICsgb2xkWF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvbGREYXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXJ0eSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGlydHk7XG59O1xuXG5mdW5jdGlvbiBjb3B5Qml0bWFwKHNyYywgc3JjU3RyaWRlLCBzcmNYLCBzcmNZLCBkc3QsIGRzdFN0cmlkZSwgZHN0WCwgZHN0WSwgd2lkdGgsIGhlaWdodCwgd3JhcCkge1xuICAgIHZhciBzcmNJID0gc3JjWSAqIHNyY1N0cmlkZSArIHNyY1g7XG4gICAgdmFyIGRzdEkgPSBkc3RZICogZHN0U3RyaWRlICsgZHN0WDtcbiAgICB2YXIgeCwgeTtcblxuICAgIGlmICh3cmFwKSB7XG4gICAgICAgIC8vIGFkZCAxIHBpeGVsIHdyYXBwZWQgcGFkZGluZyBvbiBlYWNoIHNpZGUgb2YgdGhlIGltYWdlXG4gICAgICAgIGRzdEkgLT0gZHN0U3RyaWRlO1xuICAgICAgICBmb3IgKHkgPSAtMTsgeSA8PSBoZWlnaHQ7IHkrKywgc3JjSSA9ICgoeSArIGhlaWdodCkgJSBoZWlnaHQgKyBzcmNZKSAqIHNyY1N0cmlkZSArIHNyY1gsIGRzdEkgKz0gZHN0U3RyaWRlKSB7XG4gICAgICAgICAgICBmb3IgKHggPSAtMTsgeCA8PSB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgKCh4ICsgd2lkdGgpICUgd2lkdGgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrLCBzcmNJICs9IHNyY1N0cmlkZSwgZHN0SSArPSBkc3RTdHJpZGUpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgeF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZUltYWdlID0gZnVuY3Rpb24ocGl4ZWxXaWR0aCwgcGl4ZWxIZWlnaHQpIHtcblxuICAgIC8vIEluY3JlYXNlIHRvIG5leHQgbnVtYmVyIGRpdmlzaWJsZSBieSA0LCBidXQgYXQgbGVhc3QgMS5cbiAgICAvLyBUaGlzIGlzIHNvIHdlIGNhbiBzY2FsZSBkb3duIHRoZSB0ZXh0dXJlIGNvb3JkaW5hdGVzIGFuZCBwYWNrIHRoZW1cbiAgICAvLyBpbnRvIDIgYnl0ZXMgcmF0aGVyIHRoYW4gNCBieXRlcy5cbiAgICAvLyBQYWQgaWNvbnMgdG8gcHJldmVudCB0aGVtIGZyb20gcG9sbHV0aW5nIG5laWdoYm91cnMgZHVyaW5nIGxpbmVhciBpbnRlcnBvbGF0aW9uXG4gICAgdmFyIHBhZGRpbmcgPSAyO1xuICAgIHZhciBwYWNrV2lkdGggPSBwaXhlbFdpZHRoICsgcGFkZGluZyArICg0IC0gKHBpeGVsV2lkdGggKyBwYWRkaW5nKSAlIDQpO1xuICAgIHZhciBwYWNrSGVpZ2h0ID0gcGl4ZWxIZWlnaHQgKyBwYWRkaW5nICsgKDQgLSAocGl4ZWxIZWlnaHQgKyBwYWRkaW5nKSAlIDQpOy8vICsgNDtcblxuICAgIC8vIFdlIGhhdmUgdG8gYWxsb2NhdGUgYSBuZXcgYXJlYSBpbiB0aGUgYmluLCBhbmQgc3RvcmUgYW4gZW1wdHkgaW1hZ2UgaW4gaXQuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHJlY3QgPSB0aGlzLmJpbi5hbGxvY2F0ZShwYWNrV2lkdGgsIHBhY2tIZWlnaHQpO1xuICAgIGlmIChyZWN0LncgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgfVxuXG4gICAgcmVjdC5vcmlnaW5hbFdpZHRoID0gcGl4ZWxXaWR0aDtcbiAgICByZWN0Lm9yaWdpbmFsSGVpZ2h0ID0gcGl4ZWxIZWlnaHQ7XG5cbiAgICByZXR1cm4gcmVjdDtcbn07XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uKG5hbWUsIHdyYXApIHtcbiAgICBpZiAodGhpcy5pbWFnZXNbbmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzW25hbWVdO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5zcHJpdGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHRoaXMuc3ByaXRlLmdldFNwcml0ZVBvc2l0aW9uKG5hbWUpO1xuICAgIGlmICghcG9zLndpZHRoIHx8ICFwb3MuaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciB3aWR0aCA9IHBvcy53aWR0aCAvIHBvcy5waXhlbFJhdGlvO1xuICAgIHZhciBoZWlnaHQgPSBwb3MuaGVpZ2h0IC8gcG9zLnBpeGVsUmF0aW87XG4gICAgdmFyIHJlY3QgPSB0aGlzLmFsbG9jYXRlSW1hZ2Uod2lkdGgsIGhlaWdodCk7XG4gICAgaWYgKHJlY3QudyA9PT0gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBuZXcgQXRsYXNJbWFnZShyZWN0LCB3aWR0aCwgaGVpZ2h0LCBwb3Muc2RmKTtcbiAgICB0aGlzLmltYWdlc1tuYW1lXSA9IGltYWdlO1xuXG4gICAgdGhpcy5jb3B5KHJlY3QsIHBvcywgd3JhcCk7XG5cbiAgICByZXR1cm4gaW1hZ2U7XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKG5hbWUsIHJlcGVhdGluZykge1xuICAgIHZhciBpbWFnZSA9IHRoaXMuZ2V0SW1hZ2UobmFtZSwgcmVwZWF0aW5nKTtcbiAgICB2YXIgcmVjdCA9IGltYWdlICYmIGltYWdlLnJlY3Q7XG5cbiAgICBpZiAoIXJlY3QpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB0aGUgaW1hZ2UgaXMgcmVwZWF0aW5nLCBnZXQgdGhlIGNvcnJlY3QgcG9zaXRpb24gb2YgdGhlIGltYWdlLCByYXRoZXIgdGhhbiB0aGVcbiAgICAvLyBvbmUgcm91bmRlZCB1cCB0byA0IHBpeGVscy5cbiAgICB2YXIgd2lkdGggPSByZXBlYXRpbmcgPyBpbWFnZS53aWR0aCA6IHJlY3QudztcbiAgICB2YXIgaGVpZ2h0ID0gcmVwZWF0aW5nID8gaW1hZ2UuaGVpZ2h0IDogcmVjdC5oO1xuICAgIHZhciBwYWRkaW5nID0gMTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNpemU6IFt3aWR0aCwgaGVpZ2h0XSxcbiAgICAgICAgdGw6IFsocmVjdC54ICsgcGFkZGluZykgICAgICAgICAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nKSAgICAgICAgICAvIHRoaXMuaGVpZ2h0XSxcbiAgICAgICAgYnI6IFsocmVjdC54ICsgcGFkZGluZyArIHdpZHRoKSAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nICsgaGVpZ2h0KSAvIHRoaXMuaGVpZ2h0XVxuICAgIH07XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5kYXRhKSB7XG4gICAgICAgIHZhciB3ID0gTWF0aC5mbG9vcih0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdmFyIGggPSBNYXRoLmZsb29yKHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQzMkFycmF5KHcgKiBoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24oZHN0LCBzcmMsIHdyYXApIHtcbiAgICAvLyBpZiAoIXNwcml0ZS0+cmFzdGVyKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnNwcml0ZS5pbWcuZGF0YSkgcmV0dXJuO1xuICAgIHZhciBzcmNJbWcgPSBuZXcgVWludDMyQXJyYXkodGhpcy5zcHJpdGUuaW1nLmRhdGEuYnVmZmVyKTtcblxuICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICB2YXIgZHN0SW1nID0gdGhpcy5kYXRhO1xuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuXG4gICAgY29weUJpdG1hcChcbiAgICAgICAgLyogc291cmNlIGJ1ZmZlciAqLyAgc3JjSW1nLFxuICAgICAgICAvKiBzb3VyY2Ugc3RyaWRlICovICB0aGlzLnNwcml0ZS5pbWcud2lkdGgsXG4gICAgICAgIC8qIHNvdXJjZSB4ICovICAgICAgIHNyYy54LFxuICAgICAgICAvKiBzb3VyY2UgeSAqLyAgICAgICBzcmMueSxcbiAgICAgICAgLyogZGVzdCBidWZmZXIgKi8gICAgZHN0SW1nLFxuICAgICAgICAvKiBkZXN0IHN0cmlkZSAqLyAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLFxuICAgICAgICAvKiBkZXN0IHggKi8gICAgICAgICAoZHN0LnggKyBwYWRkaW5nKSAqIHRoaXMucGl4ZWxSYXRpbyxcbiAgICAgICAgLyogZGVzdCB5ICovICAgICAgICAgKGRzdC55ICsgcGFkZGluZykgKiB0aGlzLnBpeGVsUmF0aW8sXG4gICAgICAgIC8qIGljb24gZGltZW5zaW9uICovIHNyYy53aWR0aCxcbiAgICAgICAgLyogaWNvbiBkaW1lbnNpb24gKi8gc3JjLmhlaWdodCxcbiAgICAgICAgLyogd3JhcCAqLyB3cmFwXG4gICAgKTtcblxuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLmFkZEljb25zID0gZnVuY3Rpb24oaWNvbnMsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpY29ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmdldEltYWdlKGljb25zW2ldKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCB0aGlzLmltYWdlcyk7XG59O1xuXG5TcHJpdGVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsLCBsaW5lYXIpIHtcbiAgICB2YXIgZmlyc3QgPSBmYWxzZTtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZmlyc3QgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgfVxuXG4gICAgdmFyIGZpbHRlclZhbCA9IGxpbmVhciA/IGdsLkxJTkVBUiA6IGdsLk5FQVJFU1Q7XG4gICAgaWYgKGZpbHRlclZhbCAhPT0gdGhpcy5maWx0ZXIpIHtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGZpbHRlclZhbCk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBmaWx0ZXJWYWwpO1xuICAgICAgICB0aGlzLmZpbHRlciA9IGZpbHRlclZhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kaXJ0eSkge1xuICAgICAgICB0aGlzLmFsbG9jYXRlKCk7XG5cbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIGdsLlRFWFRVUkVfMkQsIC8vIGVudW0gdGFyZ2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW5kIGxldmVsXG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gaW5kIGludGVybmFsZm9ybWF0XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgLy8gR0xzaXplaSB3aWR0aFxuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvLCAvLyBHTHNpemVpIGhlaWdodFxuICAgICAgICAgICAgICAgIDAsIC8vIGluZCBib3JkZXJcbiAgICAgICAgICAgICAgICBnbC5SR0JBLCAvLyBlbnVtIGZvcm1hdFxuICAgICAgICAgICAgICAgIGdsLlVOU0lHTkVEX0JZVEUsIC8vIGVudW0gdHlwZVxuICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KHRoaXMuZGF0YS5idWZmZXIpIC8vIE9iamVjdCBkYXRhXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChcbiAgICAgICAgICAgICAgICBnbC5URVhUVVJFXzJELCAvLyBlbnVtIHRhcmdldFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCBsZXZlbFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCB4b2Zmc2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW50IHlvZmZzZXRcbiAgICAgICAgICAgICAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLCAvLyBsb25nIHdpZHRoXG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8sIC8vIGxvbmcgaGVpZ2h0XG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gZW51bSBmb3JtYXRcbiAgICAgICAgICAgICAgICBnbC5VTlNJR05FRF9CWVRFLCAvLyBlbnVtIHR5cGVcbiAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheSh0aGlzLmRhdGEuYnVmZmVyKSAvLyBPYmplY3QgcGl4ZWxzXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuXG4gICAgICAgIC8vIERFQlVHXG4gICAgICAgIGlmICh0aGlzLmN0eCkge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmN0eC5nZXRJbWFnZURhdGEoMCwgMCwgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8pO1xuICAgICAgICAgICAgZGF0YS5kYXRhLnNldChuZXcgVWludDhDbGFtcGVkQXJyYXkodGhpcy5kYXRhLmJ1ZmZlcikpO1xuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54ICogdGhpcy5waXhlbFJhdGlvLCBmcmVlLnkgKiB0aGlzLnBpeGVsUmF0aW8sIGZyZWUudyAqIHRoaXMucGl4ZWxSYXRpbywgZnJlZS5oICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBBdGxhc0ltYWdlKHJlY3QsIHdpZHRoLCBoZWlnaHQsIHNkZikge1xuICAgIHRoaXMucmVjdCA9IHJlY3Q7XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuc2RmID0gc2RmO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBMYXRMbmcgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZycpO1xudmFyIExhdExuZ0JvdW5kcyA9IHJlcXVpcmUoJy4uL2dlby9sYXRfbG5nX2JvdW5kcycpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYW1lcmFPcHRpb25zXG4gKiBAcHJvcGVydHkge0FycmF5fSBbY2VudGVyXSBMYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIChwYXNzZWQgYXMgYFtsYXQsIGxuZ11gKVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6b29tXSBNYXAgem9vbSBsZXZlbFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtiZWFyaW5nXSBNYXAgcm90YXRpb24gYmVhcmluZyBpbiBkZWdyZWVzIGNvdW50ZXItY2xvY2t3aXNlIGZyb20gbm9ydGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcGl0Y2hdIFRoZSBhbmdsZSBhdCB3aGljaCB0aGUgY2FtZXJhIGlzIGxvb2tpbmcgYXQgdGhlIGdyb3VuZFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gW0FuaW1hdGlvbk9wdGlvbnNdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTUwMF0gTnVtYmVyIGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gW2Vhc2luZ11cbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IFtvZmZzZXQ9WzAsMF1dIHBvaW50LCBvcmlnaW4gb2YgbW92ZW1lbnQgcmVsYXRpdmUgdG8gbWFwIGNlbnRlclxuICogQHByb3BlcnR5IHtib29sZWFufSBbYW5pbWF0ZT10cnVlXSBXaGVuIHNldCB0byBmYWxzZSwgbm8gYW5pbWF0aW9uIGhhcHBlbnNcbiAqL1xuXG52YXIgQ2FtZXJhID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHt9O1xuXG51dGlsLmV4dGVuZChDYW1lcmEucHJvdG90eXBlLCAvKiogQGxlbmRzIE1hcC5wcm90b3R5cGUgKi97XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IHZpZXcgZ2VvZ3JhcGhpY2FsIHBvaW50LlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmNlbnRlcjsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgbG9jYXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjZW50ZXIgTGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSAocGFzc2VkIGFzIGBbbGF0LCBsbmddYClcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5zZXRDZW50ZXIoWy03NCwgMzhdKTtcbiAgICAgKi9cbiAgICBzZXRDZW50ZXI6IGZ1bmN0aW9uKGNlbnRlcikge1xuICAgICAgICB0aGlzLmp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUGFuIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgcGl4ZWxzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvZmZzZXQgW3gsIHldXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHBhbkJ5OiBmdW5jdGlvbihvZmZzZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5wYW5Ubyh0aGlzLnRyYW5zZm9ybS5jZW50ZXIsIHV0aWwuZXh0ZW5kKHtvZmZzZXQ6IFBvaW50LmNvbnZlcnQob2Zmc2V0KS5tdWx0KC0xKX0sIG9wdGlvbnMpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFBhbiB0byBhIGNlcnRhaW4gbG9jYXRpb24gd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBsYXRsbmcgYSBgTGF0TG5nYCBvYmplY3RcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcGFuVG86IGZ1bmN0aW9uKGxhdGxuZywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLnN0b3AoKTtcblxuICAgICAgICBsYXRsbmcgPSBMYXRMbmcuY29udmVydChsYXRsbmcpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2UsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLnJvdGF0ZSgtdHIuYW5nbGUpLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldCk7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSB0ci51bnByb2plY3QoZnJvbS5hZGQodG8uc3ViKGZyb20pLm11bHQoaykpKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgem9vbVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnRyYW5zZm9ybS56b29tOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIG1hcCB6b29tLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3pvb206IHpvb219KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBNYXAgem9vbSBsZXZlbFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gem9vbSB0aGUgbWFwIHRvIDVcbiAgICAgKiBtYXAuc2V0Wm9vbSg1KTtcbiAgICAgKi9cbiAgICBzZXRab29tOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHt6b29tOiB6b29tfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRvIGEgY2VydGFpbiB6b29tIGxldmVsIHdpdGggZWFzaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbVRvOiBmdW5jdGlvbih6b29tLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIG9wdGlvbnMuZWFzaW5nID0gdGhpcy5fdXBkYXRlRWFzaW5nKG9wdGlvbnMuZHVyYXRpb24sIHpvb20sIG9wdGlvbnMuZWFzaW5nKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLmNlbnRlcixcbiAgICAgICAgICAgIHN0YXJ0Wm9vbSA9IHRyLnpvb207XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkgb3B0aW9ucy5kdXJhdGlvbiA9IDA7XG5cbiAgICAgICAgaWYgKCF0aGlzLnpvb21pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRab29tQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0Wm9vbSwgem9vbSwgayksIGFyb3VuZCk7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmUnKS5maXJlKCd6b29tJyk7XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5lYXNlID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmR1cmF0aW9uID49IDIwMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5kdXJhdGlvbiA8IDIwMCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX29uWm9vbUVuZCk7XG4gICAgICAgICAgICB0aGlzLl9vblpvb21FbmQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCAyMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb20gaW4gYnkgMSBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHpvb21JbjogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSArIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIG91dCBieSAxIGxldmVsXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbU91dDogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSAtIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBiZWFyaW5nIGluIGRlZ3JlZXNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldEJlYXJpbmc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0uYmVhcmluZzsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgcm90YXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7YmVhcmluZzogYmVhcmluZ30pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiZWFyaW5nIE1hcCByb3RhdGlvbiBiZWFyaW5nIGluIGRlZ3JlZXMgY291bnRlci1jbG9ja3dpc2UgZnJvbSBub3J0aFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gcm90YXRlIHRoZSBtYXAgdG8gOTAgZGVncmVlc1xuICAgICAqIG1hcC5zZXRCZWFyaW5nKDkwKTtcbiAgICAgKi9cbiAgICBzZXRCZWFyaW5nOiBmdW5jdGlvbihiZWFyaW5nKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHtiZWFyaW5nOiBiZWFyaW5nfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSBiZWFyaW5nIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgZGVncmVlcyB3aXRoIGVhc2luZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGJlYXJpbmdcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcm90YXRlVG86IGZ1bmN0aW9uKGJlYXJpbmcsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBlYXNpbmc6IHV0aWwuZWFzZVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5nZXRCZWFyaW5nKCksXG4gICAgICAgICAgICBhcm91bmQgPSB0ci5jZW50ZXI7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBiZWFyaW5nID0gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhiZWFyaW5nLCBzdGFydCk7XG5cbiAgICAgICAgdGhpcy5yb3RhdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRCZWFyaW5nQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0LCBiZWFyaW5nLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtYXAgYmVhcmluZyB0byAwIChub3J0aCkgd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QW5pbWF0aW9uT3B0aW9uc31cbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICByZXNldE5vcnRoOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvdGF0ZVRvKDAsIHV0aWwuZXh0ZW5kKHtkdXJhdGlvbjogMTAwMH0sIG9wdGlvbnMpKTtcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgYW5nbGUgaW4gZGVncmVlc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0UGl0Y2g6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucGl0Y2g7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgbWFwIGFuZ2xlLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3BpdGNoOiBwaXRjaH0pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXRjaCBUaGUgYW5nbGUgYXQgd2hpY2ggdGhlIGNhbWVyYSBpcyBsb29raW5nIGF0IHRoZSBncm91bmRcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRQaXRjaDogZnVuY3Rpb24ocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8oe3BpdGNoOiBwaXRjaH0pO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIFpvb20gdG8gY29udGFpbiBjZXJ0YWluIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJvdW5kcyBbW21pbkxhdCwgbWluTG5nXSwgW21heExhdCwgbWF4TG5nXV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5zcGVlZD0xLjJdIEhvdyBmYXN0IGFuaW1hdGlvbiBvY2N1cnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuY3VydmU9MS40Ml0gSG93IG11Y2ggem9vbWluZyBvdXQgb2NjdXJzIGR1cmluZyBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmVhc2luZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLnBhZGRpbmcgaG93IG11Y2ggcGFkZGluZyB0aGVyZSBpcyBhcm91bmQgdGhlIGdpdmVuIGJvdW5kcyBvbiBlYWNoIHNpZGUgaW4gcGl4ZWxzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMubWF4Wm9vbVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIGZpdEJvdW5kczogZnVuY3Rpb24oYm91bmRzLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIG1heFpvb206IEluZmluaXR5XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIGJvdW5kcyA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KGJvdW5kcyk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLFxuICAgICAgICAgICAgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG53ID0gdHIucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxuICAgICAgICAgICAgc2UgPSB0ci5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSksXG4gICAgICAgICAgICBzaXplID0gc2Uuc3ViKG53KSxcbiAgICAgICAgICAgIHNjYWxlWCA9ICh0ci53aWR0aCAtIG9wdGlvbnMucGFkZGluZyAqIDIgLSBNYXRoLmFicyhvZmZzZXQueCkgKiAyKSAvIHNpemUueCxcbiAgICAgICAgICAgIHNjYWxlWSA9ICh0ci5oZWlnaHQgLSBvcHRpb25zLnBhZGRpbmcgKiAyIC0gTWF0aC5hYnMob2Zmc2V0LnkpICogMikgLyBzaXplLnk7XG5cbiAgICAgICAgb3B0aW9ucy5jZW50ZXIgPSB0ci51bnByb2plY3QobncuYWRkKHNlKS5kaXYoMikpO1xuICAgICAgICBvcHRpb25zLnpvb20gPSBNYXRoLm1pbih0ci5zY2FsZVpvb20odHIuc2NhbGUgKiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSkpLCBvcHRpb25zLm1heFpvb20pO1xuICAgICAgICBvcHRpb25zLmJlYXJpbmcgPSAwO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zLmxpbmVhciA/XG4gICAgICAgICAgICB0aGlzLmVhc2VUbyhvcHRpb25zKSA6XG4gICAgICAgICAgICB0aGlzLmZseVRvKG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgYW55IGNvbWJpbmF0aW9uIG9mIGNlbnRlciwgem9vbSwgYmVhcmluZywgYW5kIHBpdGNoLCB3aXRob3V0XG4gICAgICogYSB0cmFuc2l0aW9uLiBUaGUgbWFwIHdpbGwgcmV0YWluIHRoZSBjdXJyZW50IHZhbHVlcyBmb3IgYW55IG9wdGlvbnNcbiAgICAgKiBub3QgaW5jbHVkZWQgaW4gYG9wdGlvbnNgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBqdW1wVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICB6b29tQ2hhbmdlZCA9IGZhbHNlLFxuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSBmYWxzZSxcbiAgICAgICAgICAgIHBpdGNoQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICgnY2VudGVyJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3pvb20nIGluIG9wdGlvbnMgJiYgdHIuem9vbSAhPT0gK29wdGlvbnMuem9vbSkge1xuICAgICAgICAgICAgem9vbUNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuem9vbSA9ICtvcHRpb25zLnpvb207XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2JlYXJpbmcnIGluIG9wdGlvbnMgJiYgdHIuYmVhcmluZyAhPT0gK29wdGlvbnMuYmVhcmluZykge1xuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuYmVhcmluZyA9ICtvcHRpb25zLmJlYXJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3BpdGNoJyBpbiBvcHRpb25zICYmIHRyLnBpdGNoICE9PSArb3B0aW9ucy5waXRjaCkge1xuICAgICAgICAgICAgcGl0Y2hDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyLnBpdGNoID0gK29wdGlvbnMucGl0Y2g7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZScpO1xuXG4gICAgICAgIGlmICh6b29tQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5maXJlKCd6b29tJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYmVhcmluZ0NoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGl0Y2hDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3BpdGNoJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEVhc2luZyBhbmltYXRpb24gdG8gYSBzcGVjaWZpZWQgbG9jYXRpb24vem9vbS9iZWFyaW5nXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NhbWVyYU9wdGlvbnMrQW5pbWF0aW9uT3B0aW9uc30gb3B0aW9ucyBtYXAgdmlldyBhbmQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICBlYXNlVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdLFxuICAgICAgICAgICAgZHVyYXRpb246IDUwMCxcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkucm90YXRlKC10ci5hbmdsZSksXG4gICAgICAgICAgICBmcm9tID0gdHIucG9pbnQsXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgc3RhcnRQaXRjaCA9IHRoaXMuZ2V0UGl0Y2goKTtcblxuICAgICAgICB2YXIgem9vbSA9ICd6b29tJyBpbiBvcHRpb25zID8gK29wdGlvbnMuem9vbSA6IHN0YXJ0Wm9vbTtcbiAgICAgICAgdmFyIGJlYXJpbmcgPSAnYmVhcmluZycgaW4gb3B0aW9ucyA/IHRoaXMuX25vcm1hbGl6ZUJlYXJpbmcob3B0aW9ucy5iZWFyaW5nLCBzdGFydEJlYXJpbmcpIDogc3RhcnRCZWFyaW5nO1xuICAgICAgICB2YXIgcGl0Y2ggPSAncGl0Y2gnIGluIG9wdGlvbnMgPyArb3B0aW9ucy5waXRjaCA6IHN0YXJ0UGl0Y2g7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgdG8gPSAnY2VudGVyJyBpbiBvcHRpb25zID8gdHIucHJvamVjdChMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcikpLnN1YihvZmZzZXQuZGl2KHNjYWxlKSkgOiBmcm9tLFxuICAgICAgICAgICAgYXJvdW5kO1xuXG4gICAgICAgIGlmICh6b29tICE9PSBzdGFydFpvb20pIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKHRvLnN1Yihmcm9tKS5kaXYoMSAtIDEgLyBzY2FsZSkpKTtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgaWYgKHpvb20gIT09IHN0YXJ0Wm9vbSkge1xuICAgICAgICAgICAgICAgIHRyLnNldFpvb21Bcm91bmQoaW50ZXJwb2xhdGUoc3RhcnRab29tLCB6b29tLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHIuY2VudGVyID0gdHIudW5wcm9qZWN0KGZyb20uYWRkKHRvLnN1Yihmcm9tKS5tdWx0KGspKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBpdGNoICE9PSBzdGFydFBpdGNoKSB7XG4gICAgICAgICAgICAgICAgdHIucGl0Y2ggPSBpbnRlcnBvbGF0ZShzdGFydFBpdGNoLCBwaXRjaCwgayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICAgICAgaWYgKHRoaXMuem9vbWluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucm90YXRpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGbHlpbmcgYW5pbWF0aW9uIHRvIGEgc3BlY2lmaWVkIGxvY2F0aW9uL3pvb20vYmVhcmluZyB3aXRoIGF1dG9tYXRpYyBjdXJ2ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc3BlZWQ9MS4yXSBIb3cgZmFzdCBhbmltYXRpb24gb2NjdXJzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmN1cnZlPTEuNDJdIEhvdyBtdWNoIHpvb21pbmcgb3V0IG9jY3VycyBkdXJpbmcgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZWFzaW5nXVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gZmx5IHdpdGggZGVmYXVsdCBvcHRpb25zIHRvIG51bGwgaXNsYW5kXG4gICAgICogbWFwLmZseVRvKHtjZW50ZXI6IFswLCAwXSwgem9vbTogOX0pO1xuICAgICAqIC8vIHVzaW5nIGZseVRvIG9wdGlvbnNcbiAgICAgKiBtYXAuZmx5VG8oe1xuICAgICAqICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICogICB6b29tOiA5LFxuICAgICAqICAgc3BlZWQ6IDAuMixcbiAgICAgKiAgIGN1cnZlOiAxLFxuICAgICAqICAgZWFzaW5nOiBmdW5jdGlvbih0KSB7XG4gICAgICogICAgIHJldHVybiB0O1xuICAgICAqICAgfVxuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZseVRvOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIHNwZWVkOiAxLjIsXG4gICAgICAgICAgICBjdXJ2ZTogMS40MixcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpO1xuXG4gICAgICAgIHZhciBjZW50ZXIgPSAnY2VudGVyJyBpbiBvcHRpb25zID8gTGF0TG5nLmNvbnZlcnQob3B0aW9ucy5jZW50ZXIpIDogdGhpcy5nZXRDZW50ZXIoKTtcbiAgICAgICAgdmFyIHpvb20gPSAnem9vbScgaW4gb3B0aW9ucyA/ICArb3B0aW9ucy56b29tIDogc3RhcnRab29tO1xuICAgICAgICB2YXIgYmVhcmluZyA9ICdiZWFyaW5nJyBpbiBvcHRpb25zID8gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhvcHRpb25zLmJlYXJpbmcsIHN0YXJ0QmVhcmluZykgOiBzdGFydEJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGNlbnRlcikuc3ViKG9mZnNldC5kaXYoc2NhbGUpKTtcblxuICAgICAgICB2YXIgc3RhcnRXb3JsZFNpemUgPSB0ci53b3JsZFNpemUsXG4gICAgICAgICAgICByaG8gPSBvcHRpb25zLmN1cnZlLFxuICAgICAgICAgICAgViA9IG9wdGlvbnMuc3BlZWQsXG5cbiAgICAgICAgICAgIHcwID0gTWF0aC5tYXgodHIud2lkdGgsIHRyLmhlaWdodCksXG4gICAgICAgICAgICB3MSA9IHcwIC8gc2NhbGUsXG4gICAgICAgICAgICB1MSA9IHRvLnN1Yihmcm9tKS5tYWcoKSxcbiAgICAgICAgICAgIHJobzIgPSByaG8gKiByaG87XG5cbiAgICAgICAgZnVuY3Rpb24gcihpKSB7XG4gICAgICAgICAgICB2YXIgYiA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIChpID8gLTEgOiAxKSAqIHJobzIgKiByaG8yICogdTEgKiB1MSkgLyAoMiAqIChpID8gdzEgOiB3MCkgKiByaG8yICogdTEpO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubG9nKE1hdGguc3FydChiICogYiArIDEpIC0gYik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaW5oKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSAtIE1hdGguZXhwKC1uKSkgLyAyOyB9XG4gICAgICAgIGZ1bmN0aW9uIGNvc2gobikgeyByZXR1cm4gKE1hdGguZXhwKG4pICsgTWF0aC5leHAoLW4pKSAvIDI7IH1cbiAgICAgICAgZnVuY3Rpb24gdGFuaChuKSB7IHJldHVybiBzaW5oKG4pIC8gY29zaChuKTsgfVxuXG4gICAgICAgIHZhciByMCA9IHIoMCksXG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIChjb3NoKHIwKSAvIGNvc2gocjAgKyByaG8gKiBzKSk7IH0sXG4gICAgICAgICAgICB1ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHcwICogKChjb3NoKHIwKSAqIHRhbmgocjAgKyByaG8gKiBzKSAtIHNpbmgocjApKSAvIHJobzIpIC8gdTE7IH0sXG4gICAgICAgICAgICBTID0gKHIoMSkgLSByMCkgLyByaG87XG5cbiAgICAgICAgaWYgKE1hdGguYWJzKHUxKSA8IDAuMDAwMDAxKSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnModzAgLSB3MSkgPCAwLjAwMDAwMSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBrID0gdzEgPCB3MCA/IC0xIDogMTtcbiAgICAgICAgICAgIFMgPSBNYXRoLmFicyhNYXRoLmxvZyh3MSAvIHcwKSkgLyByaG87XG5cbiAgICAgICAgICAgIHUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gTWF0aC5leHAoayAqIHJobyAqIHMpOyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0aW9ucy5kdXJhdGlvbiA9IDEwMDAgKiBTIC8gVjtcblxuICAgICAgICB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuXG4gICAgICAgIHRoaXMuX2Vhc2UoZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgIHZhciBzID0gayAqIFMsXG4gICAgICAgICAgICAgICAgdXMgPSB1KHMpO1xuXG4gICAgICAgICAgICB0ci56b29tID0gc3RhcnRab29tICsgdHIuc2NhbGVab29tKDEgLyB3KHMpKTtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdCh1cykpLCBzdGFydFdvcmxkU2l6ZSk7XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgaWYgKGJlYXJpbmcgIT09IHN0YXJ0QmVhcmluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy56b29taW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGlzRWFzaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fYWJvcnRGbjtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU3RvcCBjdXJyZW50IGFuaW1hdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9hYm9ydEZuKSB7XG4gICAgICAgICAgICB0aGlzLl9hYm9ydEZuLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fYWJvcnRGbjtcblxuICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9maW5pc2hGbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2Vhc2U6IGZ1bmN0aW9uKGZyYW1lLCBmaW5pc2gsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoRm4gPSBmaW5pc2g7XG4gICAgICAgIHRoaXMuX2Fib3J0Rm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICBmcmFtZS5jYWxsKHRoaXMsIG9wdGlvbnMuZWFzaW5nKHQpKTtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2Fib3J0Rm47XG4gICAgICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5fZmluaXNoRm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgPyAwIDogb3B0aW9ucy5kdXJhdGlvbiwgdGhpcyk7XG4gICAgfSxcblxuICAgIC8vIGNvbnZlcnQgYmVhcmluZyBzbyB0aGF0IGl0J3MgbnVtZXJpY2FsbHkgY2xvc2UgdG8gdGhlIGN1cnJlbnQgb25lIHNvIHRoYXQgaXQgaW50ZXJwb2xhdGVzIHByb3Blcmx5XG4gICAgX25vcm1hbGl6ZUJlYXJpbmc6IGZ1bmN0aW9uKGJlYXJpbmcsIGN1cnJlbnRCZWFyaW5nKSB7XG4gICAgICAgIGJlYXJpbmcgPSB1dGlsLndyYXAoYmVhcmluZywgLTE4MCwgMTgwKTtcbiAgICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhiZWFyaW5nIC0gY3VycmVudEJlYXJpbmcpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyAtIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgLT0gMzYwO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyArIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgKz0gMzYwO1xuICAgICAgICByZXR1cm4gYmVhcmluZztcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUVhc2luZzogZnVuY3Rpb24oZHVyYXRpb24sIHpvb20sIGJlemllcikge1xuICAgICAgICB2YXIgZWFzaW5nO1xuXG4gICAgICAgIGlmICh0aGlzLmVhc2UpIHtcbiAgICAgICAgICAgIHZhciBlYXNlID0gdGhpcy5lYXNlLFxuICAgICAgICAgICAgICAgIHQgPSAoRGF0ZS5ub3coKSAtIGVhc2Uuc3RhcnQpIC8gZWFzZS5kdXJhdGlvbixcbiAgICAgICAgICAgICAgICBzcGVlZCA9IGVhc2UuZWFzaW5nKHQgKyAwLjAxKSAtIGVhc2UuZWFzaW5nKHQpLFxuXG4gICAgICAgICAgICAgICAgLy8gUXVpY2sgaGFjayB0byBtYWtlIG5ldyBiZXppZXIgdGhhdCBpcyBjb250aW51b3VzIHdpdGggbGFzdFxuICAgICAgICAgICAgICAgIHggPSAwLjI3IC8gTWF0aC5zcXJ0KHNwZWVkICogc3BlZWQgKyAwLjAwMDEpICogMC4wMSxcbiAgICAgICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KDAuMjcgKiAwLjI3IC0geCAqIHgpO1xuXG4gICAgICAgICAgICBlYXNpbmcgPSB1dGlsLmJlemllcih4LCB5LCAwLjI1LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyA9IGJlemllciA/IHV0aWwuYmV6aWVyLmFwcGx5KHV0aWwsIGJlemllcikgOiB1dGlsLmVhc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSBpbmZvcm1hdGlvbiBvbiBjdXJyZW50IGVhc2luZ1xuICAgICAgICB0aGlzLmVhc2UgPSB7XG4gICAgICAgICAgICBzdGFydDogKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcbiAgICAgICAgICAgIHRvOiBNYXRoLnBvdygyLCB6b29tKSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgIGVhc2luZzogZWFzaW5nXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGVhc2luZztcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBdHRyaWJ1dGlvbjtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2xcbiAqIEBjbGFzcyBBdHRyaWJ1dGlvblxuICogQGV4YW1wbGVcbiAqIG1hcC5hZGRDb250cm9sKG5ldyBtYXBib3hnbC5BdHRyaWJ1dGlvbigpKTtcbiAqL1xuZnVuY3Rpb24gQXR0cmlidXRpb24oKSB7fVxuXG5BdHRyaWJ1dGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICdib3R0b20tcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsLWF0dHJpYicsXG4gICAgICAgICAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBET00uY3JlYXRlKCdkaXYnLCBjbGFzc05hbWUsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmxvYWQnLCB0aGlzLl91cGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX3VwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgbWFwLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fdXBkYXRlLmJpbmQodGhpcykpO1xuICAgICAgICBtYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVFZGl0TGluay5iaW5kKHRoaXMpKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGF0dHJpYnV0aW9ucyA9IFtdO1xuXG4gICAgICAgIGlmICh0aGlzLl9tYXAuc3R5bGUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzW2lkXTtcbiAgICAgICAgICAgICAgICBpZiAoc291cmNlLmF0dHJpYnV0aW9uICYmIGF0dHJpYnV0aW9ucy5pbmRleE9mKHNvdXJjZS5hdHRyaWJ1dGlvbikgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9ucy5wdXNoKHNvdXJjZS5hdHRyaWJ1dGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY29udGFpbmVyLmlubmVySFRNTCA9IGF0dHJpYnV0aW9ucy5qb2luKCcgfCAnKTtcbiAgICAgICAgdGhpcy5fZWRpdExpbmsgPSB0aGlzLl9jb250YWluZXIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbWFwYm94LWltcHJvdmUtbWFwJylbMF07XG4gICAgICAgIHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVFZGl0TGluazogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9lZGl0TGluaykge1xuICAgICAgICAgICAgdmFyIGNlbnRlciA9IHRoaXMuX21hcC5nZXRDZW50ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX2VkaXRMaW5rLmhyZWYgPSAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXAtZmVlZGJhY2svIy8nICtcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyLmxuZyArICcvJyArIGNlbnRlci5sYXQgKyAnLycgKyBNYXRoLnJvdW5kKHRoaXMuX21hcC5nZXRab29tKCkgKyAxKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbnRyb2w7XG5cbi8qKlxuICogQSBiYXNlIGNsYXNzIGZvciBtYXAtcmVsYXRlZCBpbnRlcmZhY2UgZWxlbWVudHMuXG4gKlxuICogQGNsYXNzIENvbnRyb2xcbiAqL1xuZnVuY3Rpb24gQ29udHJvbCgpIHt9XG5cbkNvbnRyb2wucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIEFkZCB0aGlzIGNvbnRyb2wgdG8gdGhlIG1hcCwgcmV0dXJuaW5nIHRoZSBjb250cm9sIGl0c2VsZlxuICAgICAqIGZvciBjaGFpbmluZy4gVGhpcyB3aWxsIGluc2VydCB0aGUgY29udHJvbCdzIERPTSBlbGVtZW50IGludG9cbiAgICAgKiB0aGUgbWFwJ3MgRE9NIGVsZW1lbnQgaWYgdGhlIGNvbnRyb2wgaGFzIGEgYHBvc2l0aW9uYCBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbWFwXG4gICAgICogQHJldHVybnMge0NvbnRyb2x9IHRoaXNcbiAgICAgKi9cbiAgICBhZGRUbzogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMuX21hcCA9IG1hcDtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMucG9zaXRpb24pIHtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aGlzLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgICAgICB2YXIgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xuICAgICAgICAgICAgY29udGFpbmVyLmNsYXNzTmFtZSArPSAnIG1hcGJveGdsLWN0cmwnO1xuICAgICAgICAgICAgaWYgKHBvcy5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuaW5zZXJ0QmVmb3JlKGNvbnRhaW5lciwgY29ybmVyLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhpcyBjb250cm9sIGZyb20gdGhlIG1hcCBpdCBoYXMgYmVlbiBhZGRlZCB0by5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtDb250cm9sfSB0aGlzXG4gICAgICovXG4gICAgcmVtb3ZlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub25SZW1vdmUpIHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcbiAgICAgICAgdGhpcy5fbWFwID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOYXZpZ2F0aW9uO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuYXZpZ2F0aW9uIGNvbnRyb2wgd2l0aCB6b29tIGJ1dHRvbnMgYW5kIGEgY29tcGFzc1xuICogQGNsYXNzIE5hdmlnYXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wb3NpdGlvbj10b3AtcmlnaHRdIEEgc3RyaW5nIGluZGljYXRpbmcgdGhlIGNvbnRyb2wncyBwb3NpdGlvbiBvbiB0aGUgbWFwLiBPcHRpb25zIGFyZSBgdG9wLXJpZ2h0YCwgYHRvcC1sZWZ0YCwgYGJvdHRvbS1yaWdodGAsIGBib3R0b20tbGVmdGBcbiAqIEBleGFtcGxlXG4gKiBtYXAuYWRkQ29udHJvbChuZXcgbWFwYm94Z2wuTmF2aWdhdGlvbih7cG9zaXRpb246ICd0b3AtbGVmdCd9KSk7IC8vIHBvc2l0aW9uIGlzIG9wdGlvbmFsXG4gKi9cbmZ1bmN0aW9uIE5hdmlnYXRpb24ob3B0aW9ucykge1xuICAgIHV0aWwuc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbn1cblxuTmF2aWdhdGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICd0b3AtcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsJztcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgY2xhc3NOYW1lICsgJy1ncm91cCcsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fem9vbUluQnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLWluJywgbWFwLnpvb21Jbi5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLW91dCcsIG1hcC56b29tT3V0LmJpbmQobWFwKSk7XG4gICAgICAgIHRoaXMuX2NvbXBhc3MgPSB0aGlzLl9jcmVhdGVCdXR0b24oY2xhc3NOYW1lICsgJy1jb21wYXNzJywgbWFwLnJlc2V0Tm9ydGguYmluZChtYXApKTtcblxuICAgICAgICB2YXIgY29tcGFzc0NhbnZhcyA9IHRoaXMuX2NvbXBhc3NDYW52YXMgPSBET00uY3JlYXRlKCdjYW52YXMnLCBjbGFzc05hbWUgKyAnLWNvbXBhc3MtY2FudmFzJywgdGhpcy5fY29tcGFzcyk7XG4gICAgICAgIGNvbXBhc3NDYW52YXMuc3R5bGUuY3NzVGV4dCA9ICd3aWR0aDozMHB4OyBoZWlnaHQ6MzBweDsnO1xuICAgICAgICBjb21wYXNzQ2FudmFzLndpZHRoID0gMjYgKiAyO1xuICAgICAgICBjb21wYXNzQ2FudmFzLmhlaWdodCA9IDI2ICogMjtcblxuICAgICAgICB0aGlzLl9jb21wYXNzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uQ29tcGFzc0Rvd24uYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc01vdmUgPSB0aGlzLl9vbkNvbXBhc3NNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc1VwID0gdGhpcy5fb25Db21wYXNzVXAuYmluZCh0aGlzKTtcblxuICAgICAgICB0aGlzLl9jb21wYXNzQ3R4ID0gY29tcGFzc0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgIG1hcC5vbigncm90YXRlJywgdGhpcy5fZHJhd05vcnRoLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLl9kcmF3Tm9ydGgoKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfb25Db21wYXNzRG93bjogZnVuY3Rpb24oZSkge1xuICAgICAgICBET00uZGlzYWJsZURyYWcoKTtcblxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkNvbXBhc3NNb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQ29tcGFzc1VwKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG5cbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc01vdmU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLnNjcmVlblgsXG4gICAgICAgICAgICBkID0geCA8IDIgPyAtNSA6IC8vIGxlZnQgZWRnZSBvZiB0aGUgc2NyZWVuLCBjb250aW51ZSByb3RhdGluZ1xuICAgICAgICAgICAgICAgIHggPiB3aW5kb3cuc2NyZWVuLndpZHRoIC0gMiA/IDUgOiAvLyByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgKHggLSB0aGlzLl9wcmV2WCkgLyA0O1xuXG4gICAgICAgIHRoaXMuX21hcC5zZXRCZWFyaW5nKHRoaXMuX21hcC5nZXRCZWFyaW5nKCkgLSBkKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG4gICAgICAgIHRoaXMuX21vdmVkID0gdHJ1ZTtcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSxcblxuICAgIF9vbkNvbXBhc3NVcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQ29tcGFzc01vdmUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Db21wYXNzVXApO1xuICAgICAgICBET00uZW5hYmxlRHJhZygpO1xuXG4gICAgICAgIGlmICh0aGlzLl9tb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy5fbW92ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIERPTS5zdXBwcmVzc0NsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24oY2xhc3NOYW1lLCBmbikge1xuICAgICAgICB2YXIgYSA9IERPTS5jcmVhdGUoJ2J1dHRvbicsIGNsYXNzTmFtZSwgdGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkgeyBmbigpOyB9KTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfSxcblxuICAgIF9kcmF3Tm9ydGg6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmFkID0gMjAsXG4gICAgICAgICAgICB3aWR0aCA9IDgsXG4gICAgICAgICAgICBjZW50ZXIgPSAyNixcbiAgICAgICAgICAgIGFuZ2xlID0gdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSArIChNYXRoLlBJIC8gMiksXG4gICAgICAgICAgICBjdHggPSB0aGlzLl9jb21wYXNzQ3R4O1xuXG4gICAgICAgIHRoaXMuX2NvbXBhc3NDYW52YXMud2lkdGggPSB0aGlzLl9jb21wYXNzQ2FudmFzLndpZHRoO1xuXG4gICAgICAgIGN0eC50cmFuc2xhdGUoY2VudGVyLCBjZW50ZXIpO1xuICAgICAgICBjdHgucm90YXRlKGFuZ2xlKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnIzAwMCc7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbygtcmFkLCAwKTtcbiAgICAgICAgY3R4LmxpbmVUbygwLCB3aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gJyNiYmInO1xuICAgICAgICBjdHgubW92ZVRvKDAsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIHdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbyhyYWQsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSAnI2ZmZic7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSA0O1xuICAgICAgICBjdHgubW92ZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgd2lkdGgpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBJbnRlcmFjdGlvbiA9IHJlcXVpcmUoJy4vaW50ZXJhY3Rpb24nKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmdfYm91bmRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSGFuZGxlcnM7XG5cbmZ1bmN0aW9uIEhhbmRsZXJzKG1hcCkge1xuXG4gICAgdmFyIHJvdGF0ZUVuZDtcblxuICAgIHZhciBib3g7XG5cbiAgICB2YXIgaW5lcnRpYUxpbmVhcml0eSA9IDAuMixcbiAgICAgICAgaW5lcnRpYUVhc2luZyA9IHV0aWwuYmV6aWVyKDAsIDAsIGluZXJ0aWFMaW5lYXJpdHksIDEpO1xuXG4gICAgZnVuY3Rpb24gYm94em9vbUZpbmlzaCgpIHtcbiAgICAgICAgaWYgKGJveCkge1xuICAgICAgICAgICAgYm94LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoYm94KTtcbiAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgIGJveCA9IGZhbHNlO1xuICAgICAgICAgICAgRE9NLmVuYWJsZURyYWcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaW50ZXJhY3Rpb24gPSBuZXcgSW50ZXJhY3Rpb24obWFwLmdldENhbnZhcygpKVxuICAgICAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5sYXRMbmcgPSBtYXAudW5wcm9qZWN0KGUucG9pbnQpO1xuICAgICAgICAgICAgbWFwLmZpcmUoJ2NsaWNrJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZGJsY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnZGJsY2xpY2snLCBlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW91c2Vtb3ZlJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLnN0b3AoKTtcbiAgICAgICAgICAgIG1hcC5yZXNpemUoKTtcbiAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYgKGUuYWx0S2V5IHx8IGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHBhbiA9IDgwO1xuICAgICAgICAgICAgdmFyIHJvdGF0ZSA9IDI7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHpvb21CeSh6KSB7XG4gICAgICAgICAgICAgICAgbWFwLnpvb21UbyhNYXRoLnJvdW5kKG1hcC5nZXRab29tKCkpICsgKGUuc2hpZnRLZXkgPyAyIDogMSkgKiB6KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFuQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5wYW5CeSh2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcm90YXRlQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5zZXRCZWFyaW5nKG1hcC5nZXRCZWFyaW5nKCkgKyB2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDYxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTA3OlxuICAgICAgICAgICAgICAgIGNhc2UgMTcxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTg3OlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTg5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTA5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTczOlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoLTEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM3OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQnkoLXJvdGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5CeShbLXBhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzk6XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVCeShyb3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFuQnkoW3BhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzg6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCAtcGFuXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDA6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCBwYW5dKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIG1hcC5zdG9wKCk7XG4gICAgICAgICAgICB2YXIgbW91c2VMb2NhdGlvbiA9IG1hcC50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihlLnBvaW50LmFkZChlLm9mZnNldCkpO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5zZXRMb2NhdGlvbkF0UG9pbnQobW91c2VMb2NhdGlvbiwgZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbmVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5pbmVydGlhKSB7XG4gICAgICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29udmVydCB2ZWxvY2l0eSB0byBweC9zICYgYWRqdXN0IGZvciBpbmNyZWFzZWQgaW5pdGlhbCBhbmltYXRpb24gc3BlZWQgd2hlbiBlYXNpbmcgb3V0XG4gICAgICAgICAgICAgICAgdmFyIHZlbG9jaXR5ID0gZS5pbmVydGlhLm11bHQoMTAwMCAqIGluZXJ0aWFMaW5lYXJpdHkpLFxuICAgICAgICAgICAgICAgICAgICBzcGVlZCA9IHZlbG9jaXR5Lm1hZygpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heFNwZWVkID0gNDAwMDsgLy8gcHgvc1xuXG4gICAgICAgICAgICAgICAgaWYgKHNwZWVkID49IG1heFNwZWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwZWVkID0gbWF4U3BlZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZlbG9jaXR5Ll91bml0KCkuX211bHQobWF4U3BlZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBkZWNlbGVyYXRpb24gPSA4MDAwLCAvLyBweC9zXjJcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzcGVlZCAvIChkZWNlbGVyYXRpb24gKiBpbmVydGlhTGluZWFyaXR5KSxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gdmVsb2NpdHkubXVsdCgtZHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gICAgICAgICAgICAgICAgbWFwLnBhbkJ5KG9mZnNldCwge1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24gKiAxMDAwLFxuICAgICAgICAgICAgICAgICAgICBlYXNpbmc6IGluZXJ0aWFFYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIG5vTW92ZVN0YXJ0OiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignem9vbScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIFNjYWxlIGJ5IHNpZ21vaWQgb2Ygc2Nyb2xsIHdoZWVsIGRlbHRhLlxuICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAvICgxICsgTWF0aC5leHAoLU1hdGguYWJzKGUuZGVsdGEgLyAxMDApKSk7XG4gICAgICAgICAgICBpZiAoZS5kZWx0YSA8IDAgJiYgc2NhbGUgIT09IDApIHNjYWxlID0gMSAvIHNjYWxlO1xuXG4gICAgICAgICAgICB2YXIgZnJvbVNjYWxlID0gbWFwLmVhc2UgJiYgaXNGaW5pdGUoZS5kZWx0YSkgPyBtYXAuZWFzZS50byA6IG1hcC50cmFuc2Zvcm0uc2NhbGUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSAhaXNGaW5pdGUoZS5kZWx0YSkgPyA4MDAgOiAwO1xuXG4gICAgICAgICAgICBtYXAuem9vbVRvKG1hcC50cmFuc2Zvcm0uc2NhbGVab29tKGZyb21TY2FsZSAqIHNjYWxlKSwge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICBhcm91bmQ6IG1hcC51bnByb2plY3QoZS5wb2ludClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3JvdGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIHZhciBjZW50ZXIgPSBtYXAudHJhbnNmb3JtLmNlbnRlclBvaW50LCAvLyBDZW50ZXIgb2Ygcm90YXRpb25cbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyID0gZS5zdGFydC5zdWIoY2VudGVyKSxcbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyRGlzdCA9IHN0YXJ0VG9DZW50ZXIubWFnKCk7XG5cbiAgICAgICAgICAgIG1hcC5yb3RhdGluZyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBjbGljayB3YXMgdG9vIGNsb3NlIHRvIHRoZSBjZW50ZXIsIG1vdmUgdGhlIGNlbnRlciBvZiByb3RhdGlvbiBieSAyMDAgcGl4ZWxzXG4gICAgICAgICAgICAvLyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBjbGljay5cbiAgICAgICAgICAgIGlmIChzdGFydFRvQ2VudGVyRGlzdCA8IDIwMCkge1xuICAgICAgICAgICAgICAgIGNlbnRlciA9IGUuc3RhcnQuYWRkKG5ldyBQb2ludCgtMjAwLCAwKS5fcm90YXRlKHN0YXJ0VG9DZW50ZXIuYW5nbGUoKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYmVhcmluZ0RpZmYgPSBlLnByZXYuc3ViKGNlbnRlcikuYW5nbGVXaXRoKGUuY3VycmVudC5zdWIoY2VudGVyKSkgLyBNYXRoLlBJICogMTgwO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5iZWFyaW5nID0gbWFwLmdldEJlYXJpbmcoKSAtIGJlYXJpbmdEaWZmO1xuXG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHJvdGF0ZUVuZCk7XG4gICAgICAgICAgICByb3RhdGVFbmQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBtYXAucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBtYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgICAgICB9LCAyMDApO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2JveHpvb21zdGFydCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghYm94KSB7XG4gICAgICAgICAgICAgICAgYm94ID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWJveHpvb20nLCBtYXAuZ2V0Q29udGFpbmVyKCkpO1xuICAgICAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QuYWRkKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgICAgICBtYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gICAgICAgICAgICAgICAgRE9NLmRpc2FibGVEcmFnKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBtaW5YID0gTWF0aC5taW4oZS5zdGFydC54LCBlLmN1cnJlbnQueCk7XG4gICAgICAgICAgICB2YXIgbWF4WCA9IE1hdGgubWF4KGUuc3RhcnQueCwgZS5jdXJyZW50LngpO1xuICAgICAgICAgICAgdmFyIG1pblkgPSBNYXRoLm1pbihlLnN0YXJ0LnksIGUuY3VycmVudC55KTtcbiAgICAgICAgICAgIHZhciBtYXhZID0gTWF0aC5tYXgoZS5zdGFydC55LCBlLmN1cnJlbnQueSk7XG5cbiAgICAgICAgICAgIERPTS5zZXRUcmFuc2Zvcm0oYm94LCAndHJhbnNsYXRlKCcgKyBtaW5YICsgJ3B4LCcgKyBtaW5ZICsgJ3B4KScpO1xuICAgICAgICAgICAgYm94LnN0eWxlLndpZHRoID0gKG1heFggLSBtaW5YKSArICdweCc7XG4gICAgICAgICAgICBib3guc3R5bGUuaGVpZ2h0ID0gKG1heFkgLSBtaW5ZKSArICdweCc7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGJveHpvb21GaW5pc2goKTtcblxuICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICAgICAgbWFwLnVucHJvamVjdChlLnN0YXJ0KSxcbiAgICAgICAgICAgICAgICBtYXAudW5wcm9qZWN0KGUuY3VycmVudClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzLCB7IGxpbmVhcjogdHJ1ZSB9KS5maXJlKCdib3h6b29tZW5kJywge1xuICAgICAgICAgICAgICAgIGJveFpvb21Cb3VuZHM6IGJvdW5kc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWNhbmNlbCcsIGJveHpvb21GaW5pc2gpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogQWRkcyBwb3NpdGlvbmFsIGNvb3JkaW5hdGVzIHRvIFVSTCBoYXNoZXMuIFBhc3NlZCBhcyBhbiBvcHRpb24gdG8gdGhlIG1hcCBvYmplY3RcbiAqXG4gKiBAY2xhc3MgbWFwYm94Z2wuSGFzaFxuICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEhhc2g7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmZ1bmN0aW9uIEhhc2goKSB7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ19vbkhhc2hDaGFuZ2UnLFxuICAgICAgICAnX3VwZGF0ZUhhc2gnXG4gICAgXSwgdGhpcyk7XG59XG5cbkhhc2gucHJvdG90eXBlID0ge1xuICAgIC8qIE1hcCBlbGVtZW50IHRvIGxpc3RlbiBmb3IgY29vcmRpbmF0ZSBjaGFuZ2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwXG4gICAgICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVIYXNoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qIFJlbW92ZXMgaGFzaFxuICAgICAqXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlZW5kJywgdGhpcy5fdXBkYXRlSGFzaCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9tYXA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25IYXNoQ2hhbmdlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGxvYyA9IGxvY2F0aW9uLmhhc2gucmVwbGFjZSgnIycsICcnKS5zcGxpdCgnLycpO1xuICAgICAgICBpZiAobG9jLmxlbmd0aCA+PSAzKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAuanVtcFRvKHtcbiAgICAgICAgICAgICAgICBjZW50ZXI6IFsrbG9jWzFdLCArbG9jWzJdXSxcbiAgICAgICAgICAgICAgICB6b29tOiArbG9jWzBdLFxuICAgICAgICAgICAgICAgIGJlYXJpbmc6ICsobG9jWzNdIHx8IDApXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUhhc2g6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY2VudGVyID0gdGhpcy5fbWFwLmdldENlbnRlcigpLFxuICAgICAgICAgICAgem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCksXG4gICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5fbWFwLmdldEJlYXJpbmcoKSxcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IE1hdGgubWF4KDAsIE1hdGguY2VpbChNYXRoLmxvZyh6b29tKSAvIE1hdGguTE4yKSksXG5cbiAgICAgICAgICAgIGhhc2ggPSAnIycgKyAoTWF0aC5yb3VuZCh6b29tICogMTAwKSAvIDEwMCkgK1xuICAgICAgICAgICAgICAgICcvJyArIGNlbnRlci5sYXQudG9GaXhlZChwcmVjaXNpb24pICtcbiAgICAgICAgICAgICAgICAnLycgKyBjZW50ZXIubG5nLnRvRml4ZWQocHJlY2lzaW9uKSArXG4gICAgICAgICAgICAgICAgKGJlYXJpbmcgPyAnLycgKyAoTWF0aC5yb3VuZChiZWFyaW5nICogMTApIC8gMTApIDogJycpO1xuXG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSgnJywgJycsIGhhc2gpO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcmFjdGlvbjtcblxuLyoqXG4gKiBNb3VzZSBldmVudFxuICpcbiAqIEBldmVudCBNYXAjbW91c2Vtb3ZlXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtFdmVudH0gb3JpZ2luYWxFdmVudCB0aGUgb3JpZ2luYWwgRE9NIGV2ZW50XG4gKi9cblxuLyoqXG4gKiBEb3VibGUgY2xpY2sgZXZlbnQuXG4gKlxuICogQGV2ZW50IE1hcCNkYmxjbGlja1xuICogQHR5cGUge09iamVjdH1cbiAqIEBwcm9wZXJ0eSB7UG9pbnR9IHBvaW50IHRoZSBwaXhlbCBsb2NhdGlvbiBvZiB0aGUgZXZlbnRcbiAqL1xuXG4vKipcbiAqIFBhbiBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtQb2ludH0gb2Zmc2V0IGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBtb3ZlbWVudCBmcm9tIHRoZSBwcmV2aW91cyBtYXAgbG9jYXRpb24gdG8gdGhlIGN1cnJlbnQgb25lLlxuICovXG5cbi8qKlxuICogUGFuIGVuZCBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuZW5kXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlbG9jaXR5IGEgbWVhc3VyZSBvZiBob3cgbXVjaCBpbmVydGlhIHdhcyByZWNvcmRlZCBpbiB0aGlzIHBhbiBtb3Rpb25cbiAqL1xuXG5mdW5jdGlvbiBJbnRlcmFjdGlvbihlbCkge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHRoaXM7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuXG4gICAgdmFyIHJvdGF0aW5nID0gZmFsc2UsXG4gICAgICAgIHBhbm5lZCA9IGZhbHNlLFxuICAgICAgICBib3h6b29tID0gZmFsc2UsXG4gICAgICAgIGZpcnN0UG9zID0gbnVsbCxcbiAgICAgICAgcG9zID0gbnVsbCxcbiAgICAgICAgaW5lcnRpYSA9IG51bGwsXG4gICAgICAgIG5vdztcblxuICAgIGZ1bmN0aW9uIG1vdXNlUG9zKGUpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChcbiAgICAgICAgICAgIGUuY2xpZW50WCAtIHJlY3QubGVmdCAtIGVsLmNsaWVudExlZnQsXG4gICAgICAgICAgICBlLmNsaWVudFkgLSByZWN0LnRvcCAtIGVsLmNsaWVudFRvcCk7XG4gICAgfVxuXG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbihldikge1xuICAgICAgICByb3RhdGluZyA9IHRydWU7XG4gICAgICAgIGZpcnN0UG9zID0gcG9zID0gbW91c2VQb3MoZXYpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93biwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbm1vdXNldXAsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbm1vdXNlbW92ZSwgZmFsc2UpO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25jbGljaywgZmFsc2UpO1xuICAgIHNjcm9sbHdoZWVsKHpvb20pO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kb3VibGVjbGljaywgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUsIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywga2V5ZG93biwgZmFsc2UpO1xuXG4gICAgZnVuY3Rpb24gem9vbSh0eXBlLCBkZWx0YSwgcG9pbnQpIHtcbiAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnem9vbScsIHtcbiAgICAgICAgICAgIHNvdXJjZTogdHlwZSxcbiAgICAgICAgICAgIGRlbHRhOiBkZWx0YSxcbiAgICAgICAgICAgIHBvaW50OiBwb2ludFxuICAgICAgICB9KTtcbiAgICAgICAgaW5lcnRpYSA9IG51bGw7XG4gICAgICAgIG5vdyA9IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2NsaWNrJywge3BvaW50OiBwb2ludCwgb3JpZ2luYWxFdmVudDogZXZ9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3VzZW1vdmUocG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ21vdXNlbW92ZScsIHtwb2ludDogcG9pbnQsIG9yaWdpbmFsRXZlbnQ6IGV2fSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFuKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBwb3Muc3ViKHBvaW50KTtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3BhbicsIHtvZmZzZXQ6IG9mZnNldCwgcG9pbnQ6IHBvaW50fSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCBhbiBhdmVyYWdlZCB2ZXJzaW9uIG9mIHRoaXMgbW92ZW1lbnQgdG8gdGhlIGluZXJ0aWEgdmVjdG9yXG4gICAgICAgICAgICBpZiAoaW5lcnRpYSkge1xuICAgICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBub3c7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRpbWVzIGl0J3MgMCBhZnRlciBzb21lIGVycmF0aWMgcGFuaW5nXG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lID0gZHVyYXRpb24gKyBub3c7XG4gICAgICAgICAgICAgICAgICAgIGluZXJ0aWEucHVzaChbdGltZSwgcG9pbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGluZXJ0aWEubGVuZ3RoID4gMiAmJiB0aW1lIC0gaW5lcnRpYVswXVswXSA+IDEwMCkgaW5lcnRpYS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmVydGlhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgcG9zID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUoKSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3Jlc2l6ZScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtleWRvd24oZXYpIHtcbiAgICAgICAgaWYgKGJveHpvb20gJiYgZXYua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21jYW5jZWwnKTtcbiAgICAgICAgICAgIGJveHpvb20gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2tleWRvd24nLCBldik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcm90YXRlKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3JvdGF0ZScsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogZmlyc3RQb3MsXG4gICAgICAgICAgICAgICAgcHJldjogcG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IHBvaW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvcyA9IHBvaW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG91YmxlY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2RibGNsaWNrJywge1xuICAgICAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZWRvd24oZXYpIHtcbiAgICAgICAgZmlyc3RQb3MgPSBwb3MgPSBtb3VzZVBvcyhldik7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2Rvd24nKTtcbiAgICAgICAgaWYgKGV2LnNoaWZ0S2V5IHx8ICgoZXYud2hpY2ggPT09IDEpICYmIChldi5idXR0b24gPT09IDEpKSkge1xuICAgICAgICAgIGJveHpvb20gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZXVwKGV2KSB7XG4gICAgICAgIHBhbm5lZCA9IHBvcyAmJiBmaXJzdFBvcyAmJiAocG9zLnggIT09IGZpcnN0UG9zLnggfHwgcG9zLnkgIT09IGZpcnN0UG9zLnkpO1xuXG4gICAgICAgIHJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgIHBvcyA9IG51bGw7XG5cbiAgICAgICAgaWYgKGJveHpvb20pIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21lbmQnLCB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGZpcnN0UG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IG1vdXNlUG9zKGV2KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBib3h6b29tID0gZmFsc2U7XG5cbiAgICAgICAgfSBlbHNlIGlmIChpbmVydGlhICYmIGluZXJ0aWEubGVuZ3RoID49IDIgJiYgbm93ID4gRGF0ZS5ub3coKSAtIDEwMCkge1xuICAgICAgICAgICAgdmFyIGxhc3QgPSBpbmVydGlhW2luZXJ0aWEubGVuZ3RoIC0gMV0sXG4gICAgICAgICAgICAgICAgZmlyc3QgPSBpbmVydGlhWzBdLFxuICAgICAgICAgICAgICAgIHZlbG9jaXR5ID0gbGFzdFsxXS5zdWIoZmlyc3RbMV0pLmRpdihsYXN0WzBdIC0gZmlyc3RbMF0pO1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgncGFuZW5kJywge2luZXJ0aWE6IHZlbG9jaXR5fSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChwb3MpIHtcbiAgICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdwYW5lbmQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluZXJ0aWEgPSBudWxsO1xuICAgICAgICBub3cgPSBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubW91c2Vtb3ZlKGV2KSB7XG4gICAgICAgIHZhciBwb2ludCA9IG1vdXNlUG9zKGV2KTtcblxuICAgICAgICBpZiAoYm94em9vbSkge1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnYm94em9vbXN0YXJ0Jywge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBmaXJzdFBvcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50OiBwb2ludFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyb3RhdGluZykge1xuICAgICAgICAgICAgcm90YXRlKHBvaW50KTtcblxuICAgICAgICB9IGVsc2UgaWYgKHBvcykge1xuICAgICAgICAgICAgcGFuKHBvaW50KTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhcmdldCA9IGV2LnRvRWxlbWVudCB8fCBldi50YXJnZXQ7XG4gICAgICAgICAgICB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldCAhPT0gZWwgJiYgdGFyZ2V0LnBhcmVudE5vZGUpIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICBtb3VzZW1vdmUocG9pbnQsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uY2xpY2soZXYpIHtcbiAgICAgICAgaWYgKCFwYW5uZWQpIGNsaWNrKG1vdXNlUG9zKGV2KSwgZXYpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uZG91YmxlY2xpY2soZXYpIHtcbiAgICAgICAgZG91YmxlY2xpY2sobW91c2VQb3MoZXYpLCBldik7XG4gICAgICAgIHpvb20oJ3doZWVsJywgSW5maW5pdHkgKiAoZXYuc2hpZnRLZXkgPyAtMSA6IDEpLCBtb3VzZVBvcyhldikpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbHdoZWVsKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmaXJlZm94ID0gL0ZpcmVmb3gvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgc2FmYXJpID0gL1NhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIS9DaHJvbShpdW18ZSkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgdGltZSA9IHdpbmRvdy5wZXJmb3JtYW5jZSB8fCBEYXRlO1xuXG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgd2hlZWwsIGZhbHNlKTtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V3aGVlbCcsIG1vdXNld2hlZWwsIGZhbHNlKTtcblxuICAgICAgICB2YXIgbGFzdEV2ZW50ID0gMDtcblxuICAgICAgICB2YXIgdHlwZSA9IG51bGw7XG4gICAgICAgIHZhciB0eXBlVGltZW91dCA9IG51bGw7XG4gICAgICAgIHZhciBpbml0aWFsVmFsdWUgPSBudWxsO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNjcm9sbCh2YWx1ZSwgZXYpIHtcbiAgICAgICAgICAgIHZhciBzdGFtcCA9IHRpbWUubm93KCk7XG4gICAgICAgICAgICB2YXIgdGltZURlbHRhID0gc3RhbXAgLSBsYXN0RXZlbnQ7XG4gICAgICAgICAgICBsYXN0RXZlbnQgPSBzdGFtcDtcblxuICAgICAgICAgICAgdmFyIHBvaW50ID0gbW91c2VQb3MoZXYpO1xuXG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IDAgJiYgKHZhbHVlICUgNC4wMDAyNDQxNDA2MjUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIG1vdXNlIHdoZWVsIGV2ZW50LlxuICAgICAgICAgICAgICAgIHR5cGUgPSAnd2hlZWwnO1xuICAgICAgICAgICAgICAgIC8vIE5vcm1hbGl6ZSB0aGlzIHZhbHVlIHRvIG1hdGNoIHRyYWNrcGFkLlxuICAgICAgICAgICAgICAgIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSAvIDQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSAhPT0gMCAmJiBNYXRoLmFicyh2YWx1ZSkgPCA0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIHRyYWNrcGFkIGV2ZW50IGJlY2F1c2UgaXQgaXMgc28gc21hbGwuXG4gICAgICAgICAgICAgICAgdHlwZSA9ICd0cmFja3BhZCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRpbWVEZWx0YSA+IDQwMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgbGlrZWx5IGEgbmV3IHNjcm9sbCBhY3Rpb24uXG4gICAgICAgICAgICAgICAgdHlwZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgLy8gU3RhcnQgYSB0aW1lb3V0IGluIGNhc2UgdGhpcyB3YXMgYSBzaW5ndWxhciBldmVudCwgYW5kIGRlbHkgaXRcbiAgICAgICAgICAgICAgICAvLyBieSB1cCB0byA0MG1zLlxuICAgICAgICAgICAgICAgIHR5cGVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICd3aGVlbCc7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHR5cGUsIC1pbml0aWFsVmFsdWUsIHBvaW50KTtcbiAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVwZWF0aW5nIGV2ZW50LCBidXQgd2UgZG9uJ3Qga25vdyB0aGUgdHlwZSBvZiBldmVudFxuICAgICAgICAgICAgICAgIC8vIGp1c3QgeWV0LiBJZiB0aGUgZGVsdGEgcGVyIHRpbWUgaXMgc21hbGwsIHdlIGFzc3VtZSBpdCdzIGFcbiAgICAgICAgICAgICAgICAvLyBmYXN0IHRyYWNrcGFkOyBvdGhlcndpc2Ugd2Ugc3dpdGNoIGludG8gd2hlZWwgbW9kZS5cbiAgICAgICAgICAgICAgICB0eXBlID0gKE1hdGguYWJzKHRpbWVEZWx0YSAqIHZhbHVlKSA8IDIwMCkgPyAndHJhY2twYWQnIDogJ3doZWVsJztcblxuICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgZGVsYXllZCBldmVudCBpc24ndCBmaXJlZCBhZ2FpbiwgYmVjYXVzZSB3ZVxuICAgICAgICAgICAgICAgIC8vIGFjY3VtdWxhdGUgdGhlIHByZXZpb3VzIGV2ZW50ICh3aGljaCB3YXMgbGVzcyB0aGFuIDQwbXMgYWdvKSBpbnRvXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBldmVudC5cbiAgICAgICAgICAgICAgICBpZiAodHlwZVRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHR5cGVUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZVRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBpbml0aWFsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTbG93IGRvd24gem9vbSBpZiBzaGlmdCBrZXkgaXMgaGVsZCBmb3IgbW9yZSBwcmVjaXNlIHpvb21pbmdcbiAgICAgICAgICAgIGlmIChldi5zaGlmdEtleSAmJiB2YWx1ZSkgdmFsdWUgPSB2YWx1ZSAvIDQ7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZmlyZSB0aGUgY2FsbGJhY2sgaWYgd2UgYWN0dWFsbHkga25vdyB3aGF0IHR5cGUgb2Ygc2Nyb2xsaW5nXG4gICAgICAgICAgICAvLyBkZXZpY2UgdGhlIHVzZXIgdXNlcy5cbiAgICAgICAgICAgIGlmICh0eXBlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sodHlwZSwgLXZhbHVlLCBwb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gZS5kZWx0YVk7XG4gICAgICAgICAgICAvLyBGaXJlZm94IGRvdWJsZXMgdGhlIHZhbHVlcyBvbiByZXRpbmEgc2NyZWVucy4uLlxuICAgICAgICAgICAgaWYgKGZpcmVmb3ggJiYgZS5kZWx0YU1vZGUgPT09IHdpbmRvdy5XaGVlbEV2ZW50LkRPTV9ERUxUQV9QSVhFTCkgZGVsdGFZIC89IGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gd2luZG93LldoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIGRlbHRhWSAqPSA0MDtcbiAgICAgICAgICAgIHNjcm9sbChkZWx0YVksIGUpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2V3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gLWUud2hlZWxEZWx0YVk7XG4gICAgICAgICAgICBpZiAoc2FmYXJpKSBkZWx0YVkgPSBkZWx0YVkgLyAzO1xuICAgICAgICAgICAgc2Nyb2xsKGRlbHRhWSwgZSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbkludGVyYWN0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRlZCk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBDYW52YXMgPSByZXF1aXJlKCcuLi91dGlsL2NhbnZhcycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG5cbnZhciBTdHlsZSA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlJyk7XG52YXIgQW5pbWF0aW9uTG9vcCA9IHJlcXVpcmUoJy4uL3N0eWxlL2FuaW1hdGlvbl9sb29wJyk7XG52YXIgUGFpbnRlciA9IHJlcXVpcmUoJy4uL3JlbmRlci9wYWludGVyJyk7XG5cbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuLi9nZW8vdHJhbnNmb3JtJyk7XG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xudmFyIEhhbmRsZXJzID0gcmVxdWlyZSgnLi9oYW5kbGVycycpO1xudmFyIENhbWVyYSA9IHJlcXVpcmUoJy4vY2FtZXJhJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBMYXRMbmdCb3VuZHMgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQXR0cmlidXRpb24gPSByZXF1aXJlKCcuL2NvbnRyb2wvYXR0cmlidXRpb24nKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbWFwIGluc3RhbmNlLlxuICogQGNsYXNzIE1hcFxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbnRhaW5lciBIVE1MIGVsZW1lbnQgdG8gaW5pdGlhbGl6ZSB0aGUgbWFwIGluIChvciBlbGVtZW50IGlkIGFzIHN0cmluZylcbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW5ab29tPTBdIE1pbmltdW0gem9vbSBvZiB0aGUgbWFwXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4Wm9vbT0yMF0gTWF4aW11bSB6b29tIG9mIHRoZSBtYXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnN0eWxlIE1hcCBzdHlsZSBhbmQgZGF0YSBzb3VyY2UgZGVmaW5pdGlvbiAoZWl0aGVyIGEgSlNPTiBvYmplY3Qgb3IgYSBKU09OIFVSTCksIGRlc2NyaWJlZCBpbiB0aGUgW3N0eWxlIHJlZmVyZW5jZV0oaHR0cHM6Ly9tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuaGFzaD1mYWxzZV0gSWYgYHRydWVgLCB0aGUgbWFwIHdpbGwgdHJhY2sgYW5kIHVwZGF0ZSB0aGUgcGFnZSBVUkwgYWNjb3JkaW5nIHRvIG1hcCBwb3NpdGlvblxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbnRlcmFjdGl2ZT10cnVlXSBJZiBgZmFsc2VgLCBubyBtb3VzZSwgdG91Y2gsIG9yIGtleWJvYXJkIGxpc3RlbmVycyBhcmUgYXR0YWNoZWQgdG8gdGhlIG1hcCwgc28gaXQgd2lsbCBub3QgcmVzcG9uZCB0byBpbnB1dFxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5jbGFzc2VzIFN0eWxlIGNsYXNzIG5hbWVzIHdpdGggd2hpY2ggdG8gaW5pdGlhbGl6ZSB0aGUgbWFwXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9ZmFsc2VdIElmIGB0cnVlYCwgbWFwIGNyZWF0aW9uIHdpbGwgZmFpbCBpZiB0aGUgaW1wbGVtZW50YXRpb24gZGV0ZXJtaW5lcyB0aGF0IHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgY3JlYXRlZCBXZWJHTCBjb250ZXh0IHdvdWxkIGJlIGRyYW1hdGljYWxseSBsb3dlciB0aGFuIGV4cGVjdGVkLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXI9ZmFsc2VdIElmIGB0cnVlYCwgVGhlIG1hcHMgY2FudmFzIGNhbiBiZSBleHBvcnRlZCB0byBhIFBORyB1c2luZyBgbWFwLmdldENhbnZhcygpLnRvRGF0YVVSTCgpO2AuIFRoaXMgaXMgZmFsc2UgYnkgZGVmYXVsdCBhcyBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgbWFwID0gbmV3IG1hcGJveGdsLk1hcCh7XG4gKiAgIGNvbnRhaW5lcjogJ21hcCcsXG4gKiAgIGNlbnRlcjogWzM3Ljc3MjUzNywgLTEyMi40MjA2NzldLFxuICogICB6b29tOiAxMyxcbiAqICAgc3R5bGU6IHN0eWxlX29iamVjdCxcbiAqICAgaGFzaDogdHJ1ZVxuICogfSk7XG4gKi9cbnZhciBNYXAgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB1dGlsLmluaGVyaXQodGhpcy5vcHRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuYW5pbWF0aW9uTG9vcCA9IG5ldyBBbmltYXRpb25Mb29wKCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSBuZXcgVHJhbnNmb3JtKG9wdGlvbnMubWluWm9vbSwgb3B0aW9ucy5tYXhab29tKTtcblxuICAgIGlmIChvcHRpb25zLm1heEJvdW5kcykge1xuICAgICAgICB2YXIgYiA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KG9wdGlvbnMubWF4Qm91bmRzKTtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2UgPSBbYi5nZXRTb3V0aCgpLCBiLmdldE5vcnRoKCldO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZSA9IFtiLmdldFdlc3QoKSwgYi5nZXRFYXN0KCldO1xuICAgIH1cblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFN0eWxlRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRTb3VyY2VFdmVudCcsXG4gICAgICAgICdfZm9yd2FyZExheWVyRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRUaWxlRXZlbnQnLFxuICAgICAgICAnX29uU3R5bGVMb2FkJyxcbiAgICAgICAgJ19vblN0eWxlQ2hhbmdlJyxcbiAgICAgICAgJ19vblNvdXJjZUFkZCcsXG4gICAgICAgICdfb25Tb3VyY2VSZW1vdmUnLFxuICAgICAgICAnX29uU291cmNlVXBkYXRlJyxcbiAgICAgICAgJ3VwZGF0ZScsXG4gICAgICAgICdyZW5kZXInXG4gICAgXSwgdGhpcyk7XG5cbiAgICB0aGlzLl9zZXR1cENvbnRhaW5lcigpO1xuICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuXG4gICAgdGhpcy5vbignbW92ZScsIHRoaXMudXBkYXRlKTtcbiAgICB0aGlzLm9uKCd6b29tJywgdGhpcy51cGRhdGUuYmluZCh0aGlzLCB0cnVlKSk7XG4gICAgdGhpcy5vbignbW92ZWVuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3Auc2V0KDMwMCk7IC8vIHRleHQgZmFkaW5nXG4gICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuaGFuZGxlcnMgPSBvcHRpb25zLmludGVyYWN0aXZlICYmIG5ldyBIYW5kbGVycyh0aGlzKTtcblxuICAgIHRoaXMuX2hhc2ggPSBvcHRpb25zLmhhc2ggJiYgKG5ldyBIYXNoKCkpLmFkZFRvKHRoaXMpO1xuICAgIC8vIGRvbid0IHNldCBwb3NpdGlvbiBmcm9tIG9wdGlvbnMgaWYgc2V0IHRocm91Z2ggaGFzaFxuICAgIGlmICghdGhpcy5faGFzaCB8fCAhdGhpcy5faGFzaC5fb25IYXNoQ2hhbmdlKCkpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8ob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VzID0ge307XG4gICAgdGhpcy5zdGFja3MgPSB7fTtcbiAgICB0aGlzLl9jbGFzc2VzID0ge307XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgaWYgKG9wdGlvbnMuY2xhc3NlcykgdGhpcy5zZXRDbGFzc2VzKG9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgaWYgKG9wdGlvbnMuc3R5bGUpIHRoaXMuc2V0U3R5bGUob3B0aW9ucy5zdHlsZSk7XG4gICAgaWYgKG9wdGlvbnMuYXR0cmlidXRpb25Db250cm9sKSB0aGlzLmFkZENvbnRyb2wobmV3IEF0dHJpYnV0aW9uKCkpO1xufTtcblxudXRpbC5leHRlbmQoTWFwLnByb3RvdHlwZSwgRXZlbnRlZCk7XG51dGlsLmV4dGVuZChNYXAucHJvdG90eXBlLCBDYW1lcmEucHJvdG90eXBlKTtcbnV0aWwuZXh0ZW5kKE1hcC5wcm90b3R5cGUsIC8qKiBAbGVuZHMgTWFwLnByb3RvdHlwZSAqL3tcblxuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICAgIHpvb206IDAsXG4gICAgICAgIGJlYXJpbmc6IDAsXG4gICAgICAgIHBpdGNoOiAwLFxuXG4gICAgICAgIG1pblpvb206IDAsXG4gICAgICAgIG1heFpvb206IDIwLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICBoYXNoOiBmYWxzZSxcblxuICAgICAgICBhdHRyaWJ1dGlvbkNvbnRyb2w6IHRydWUsXG5cbiAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogZmFsc2UsXG4gICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2VcbiAgICB9LFxuXG4gICAgYWRkQ29udHJvbDogZnVuY3Rpb24oY29udHJvbCkge1xuICAgICAgICBjb250cm9sLmFkZFRvKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHR5cGVkZWYge09iamVjdH0gW3N0eWxlT3B0aW9uc11cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtzdHlsZU9wdGlvbnMudHJhbnNpdGlvbj10cnVlXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHN0eWxlIGNsYXNzIHRvIGEgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2xhc3MgbmFtZSBvZiBzdHlsZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7c3R5bGVPcHRpb25zfSBvcHRpb25zXG4gICAgICogQGZpcmVzIGNoYW5nZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZENsYXNzOiBmdW5jdGlvbihrbGFzcywgb3B0aW9ucykge1xuICAgICAgICBpZiAodGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc10gPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIHN0eWxlIGNsYXNzIGZyb20gYSBtYXBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBuYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghdGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBhZGQgbW9yZSB0aGFuIG9uZSBjbGFzc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBrbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0Q2xhc3NlczogZnVuY3Rpb24oa2xhc3Nlcywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLl9jbGFzc2VzID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc2VzW2ldXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcywgb3B0aW9ucyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoZWNrIHdoZXRoZXIgYSBzdHlsZSBjbGFzcyBpcyBhY3RpdmVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBOYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgYWN0aXZlIHN0eWxlIGNsYXNzZXNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldENsYXNzZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fY2xhc3Nlcyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIERldGVjdCB0aGUgbWFwJ3MgbmV3IHdpZHRoIGFuZCBoZWlnaHQgYW5kIHJlc2l6ZSBpdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlc2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDAsIGhlaWdodCA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGggfHwgNDAwO1xuICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAzMDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jYW52YXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMudHJhbnNmb3JtLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0uX2NvbnN0cmFpbigpO1xuXG4gICAgICAgIHRoaXMucGFpbnRlci5yZXNpemUod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIC5maXJlKCdtb3Zlc3RhcnQnKVxuICAgICAgICAgICAgLmZpcmUoJ21vdmUnKVxuICAgICAgICAgICAgLmZpcmUoJ3Jlc2l6ZScpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1hcCdzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN9XG4gICAgICovXG4gICAgZ2V0Qm91bmRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyBQb2ludCgwLCAwKSksXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKHRoaXMudHJhbnNmb3JtLnNpemUpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHBpeGVsIGNvb3JkaW5hdGVzIChyZWxhdGl2ZSB0byBtYXAgY29udGFpbmVyKSBnaXZlbiBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IGB4YCBhbmQgYHlgIGNvb3JkaW5hdGVzXG4gICAgICovXG4gICAgcHJvamVjdDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybS5sb2NhdGlvblBvaW50KExhdExuZy5jb252ZXJ0KGxhdGxuZykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGdpdmVuIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHBvaW50IFt4LCB5XSBwaXhlbCBjb29yZGluYXRlc1xuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgdW5wcm9qZWN0OiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZmVhdHVyZXMgYXQgYSBwb2ludCAoW3gsIHldKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBwb2ludCBbeCwgeV0gcGl4ZWwgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwYXJhbXMucmFkaXVzPTBdIE9wdGlvbmFsLiBSYWRpdXMgaW4gcGl4ZWxzIHRvIHNlYXJjaCBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMubGF5ZXIgT3B0aW9uYWwuIE9ubHkgcmV0dXJuIGZlYXR1cmVzIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMudHlwZSBPcHRpb25hbC4gRWl0aGVyIGByYXN0ZXJgIG9yIGB2ZWN0b3JgXG4gICAgICogQHBhcmFtIHtmZWF0dXJlc0F0Q2FsbGJhY2t9IGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcmVzcG9uc2VcbiAgICAgKlxuICAgICAqIEBjYWxsYmFjayBmZWF0dXJlc0F0Q2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge09iamVjdHxudWxsfSBlcnIgRXJyb3IgX0lmIGFueV9cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmZWF0dXJlcyBEaXNwbGF5cyBhIEpTT04gYXJyYXkgb2YgZmVhdHVyZXMgZ2l2ZW4gdGhlIHBhc3NlZCBwYXJhbWV0ZXJzIG9mIGBmZWF0dXJlc0F0YFxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5mZWF0dXJlc0F0KFsxMCwgMjBdLCB7IHJhZGl1czogMTAgfSwgZnVuY3Rpb24oZXJyLCBmZWF0dXJlcykge1xuICAgICAqICAgY29uc29sZS5sb2coZmVhdHVyZXMpO1xuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBjb29yZCA9IHRoaXMudHJhbnNmb3JtLnBvaW50Q29vcmRpbmF0ZShQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgICAgIHRoaXMuc3R5bGUuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgbWFwJ3Mgc3R5bGUgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3R5bGUgQSBzdHlsZSBvYmplY3QgZm9ybWF0dGVkIGFzIEpTT05cbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRTdHlsZTogZnVuY3Rpb24oc3R5bGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGVcbiAgICAgICAgICAgICAgICAub2ZmKCdsb2FkJywgdGhpcy5fb25TdHlsZUxvYWQpXG4gICAgICAgICAgICAgICAgLm9mZignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vblN0eWxlQ2hhbmdlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ3NvdXJjZS5hZGQnLCB0aGlzLl9vblNvdXJjZUFkZClcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmxvYWQnLCB0aGlzLl9vblNvdXJjZVVwZGF0ZSlcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UuZXJyb3InLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLmFkZCcsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCd0aWxlLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLl9yZW1vdmUoKTtcblxuICAgICAgICAgICAgdGhpcy5vZmYoJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5vZmYoJ3BpdGNoJywgdGhpcy5zdHlsZS5fcmVkb1BsYWNlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN0eWxlKSB7XG4gICAgICAgICAgICB0aGlzLnN0eWxlID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2UgaWYgKHN0eWxlIGluc3RhbmNlb2YgU3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBuZXcgU3R5bGUoc3R5bGUsIHRoaXMuYW5pbWF0aW9uTG9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0eWxlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9vblN0eWxlTG9hZClcbiAgICAgICAgICAgIC5vbignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdGhpcy5fb25TdHlsZUNoYW5nZSlcbiAgICAgICAgICAgIC5vbignc291cmNlLmFkZCcsIHRoaXMuX29uU291cmNlQWRkKVxuICAgICAgICAgICAgLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5sb2FkJywgdGhpcy5fb25Tb3VyY2VVcGRhdGUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgLm9uKCdsYXllci5hZGQnLCB0aGlzLl9mb3J3YXJkTGF5ZXJFdmVudClcbiAgICAgICAgICAgIC5vbignbGF5ZXIucmVtb3ZlJywgdGhpcy5fZm9yd2FyZExheWVyRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCd0aWxlLmxvYWQnLCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpO1xuXG4gICAgICAgIHRoaXMub24oJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICB0aGlzLm9uKCdwaXRjaCcsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBzb3VyY2UgdG8gdGhlIG1hcCBzdHlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJRCBvZiB0aGUgc291cmNlLiBNdXN0IG5vdCBiZSB1c2VkIGJ5IGFueSBleGlzdGluZyBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBzb3VyY2Ugc3BlY2lmaWNhdGlvbiwgZm9sbG93aW5nIHRoZVxuICAgICAqIFtNYXBib3ggR0wgU3R5bGUgUmVmZXJlbmNlXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNzb3VyY2VzKVxuICAgICAqIEBmaXJlcyBzb3VyY2UuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkU291cmNlOiBmdW5jdGlvbihpZCwgc291cmNlKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuYWRkU291cmNlKGlkLCBzb3VyY2UpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFuIGV4aXN0aW5nIHNvdXJjZSBmcm9tIHRoZSBtYXAgc3R5bGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSUQgb2YgdGhlIHNvdXJjZSB0byByZW1vdmVcbiAgICAgKiBAZmlyZXMgc291cmNlLnJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZVNvdXJjZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5yZW1vdmVTb3VyY2UoaWQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBzdHlsZSBzb3VyY2Ugb2JqZWN0IHdpdGggdGhlIGdpdmVuIGBpZGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgc291cmNlIElEXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRTb3VyY2U6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFNvdXJjZShpZCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGxheWVyIHRvIHRoZSBtYXAgc3R5bGUuIFRoZSBsYXllciB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGUgbGF5ZXIgd2l0aFxuICAgICAqIElEIGBiZWZvcmVgLCBvciBhcHBlbmRlZCBpZiBgYmVmb3JlYCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7U3R5bGVMYXllcnxPYmplY3R9IGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSBiZWZvcmUgIElEIG9mIGFuIGV4aXN0aW5nIGxheWVyIHRvIGluc2VydCBiZWZvcmVcbiAgICAgKiBAZmlyZXMgbGF5ZXIuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkTGF5ZXI6IGZ1bmN0aW9uKGxheWVyLCBiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5hZGRMYXllcihsYXllciwgYmVmb3JlKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gYGlkYCBmcm9tIHRoZSBtYXAuIEFueSBsYXllcnMgd2hpY2ggcmVmZXIgdG8gdGhlXG4gICAgICogc3BlY2lmaWVkIGxheWVyIHZpYSBhIGByZWZgIHByb3BlcnR5IGFyZSBhbHNvIHJlbW92ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgbGF5ZXIgaWRcbiAgICAgKiBAZmlyZXMgbGF5ZXIucmVtb3ZlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZUxheWVyOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB0aGlzLnN0eWxlLnJlbW92ZUxheWVyKGlkKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZmlsdGVyIGZvciBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXIgZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0RmlsdGVyOiBmdW5jdGlvbihsYXllciwgZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuc2V0RmlsdGVyKGxheWVyLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBmaWx0ZXIgZm9yIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICovXG4gICAgZ2V0RmlsdGVyOiBmdW5jdGlvbihsYXllcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHlsZS5nZXRGaWx0ZXIobGF5ZXIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHZhbHVlIG9mIGEgcGFpbnQgcHJvcGVydHkgaW4gYSBnaXZlbiBzdHlsZSBsYXllci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYXllciBJRCBvZiBhIGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgbmFtZSBvZiBhIHBhaW50IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIHBhaW50IHByb3Blcnk7IG11c3QgaGF2ZSB0aGUgdHlwZSBhcHByb3ByaWF0ZSBmb3IgdGhlIHByb3BlcnR5IGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB0aGlzLnN0eWxlLnNldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcyk7XG4gICAgICAgIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMudXBkYXRlKHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB2YWx1ZSBvZiBhIHBhaW50IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBwYWludCBwcm9wZXJ0eVxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0ga2xhc3Mgb3B0aW9uYWwgY2xhc3Mgc3BlY2lmaWVyIGZvciB0aGUgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdmFsdWUgZm9yIHRoZSBwYWludCBwcm9wZXJ5XG4gICAgICovXG4gICAgZ2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIGtsYXNzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIGtsYXNzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB2YWx1ZSBvZiBhIGxheW91dCBwcm9wZXJ0eSBpbiBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIGEgbGF5b3V0IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIGxheW91dCBwcm9wZXJ5OyBtdXN0IGhhdmUgdGhlIHR5cGUgYXBwcm9wcmlhdGUgZm9yIHRoZSBwcm9wZXJ0eSBhcyBkZWZpbmVkIGluIHRoZSBbU3R5bGUgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXBib3gtZ2wtc3R5bGUtc3BlYy8pXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnN0eWxlLnNldExheW91dFByb3BlcnR5KGxheWVyLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHZhbHVlIG9mIGEgbGF5b3V0IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMgeyp9IHZhbHVlIGZvciB0aGUgbGF5b3V0IHByb3BlcnlcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGF5b3V0UHJvcGVydHkobGF5ZXIsIG5hbWUpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIE1hcCdzIGNvbnRhaW5lciBhcyBhbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGFpbmVyIGZvciB0aGUgbWFwIGBjYW52YXNgIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBhZGQgbm9uLUdMIG92ZXJsYXlzIHRvIHRoZSBtYXAsIHlvdSBzaG91bGQgYXBwZW5kIHRoZW0gdG8gdGhpcyBlbGVtZW50LiBUaGlzXG4gICAgICogaXMgdGhlIGVsZW1lbnQgdG8gd2hpY2ggZXZlbnQgYmluZGluZ3MgZm9yIG1hcCBpbnRlcmFjdGl2aXR5IHN1Y2ggYXMgcGFubmluZyBhbmQgem9vbWluZyBhcmVcbiAgICAgKiBhdHRhY2hlZC4gSXQgd2lsbCByZWNlaXZlIGJ1YmJsZWQgZXZlbnRzIGZvciBjaGlsZCBlbGVtZW50cyBzdWNoIGFzIHRoZSBgY2FudmFzYCwgYnV0IG5vdCBmb3JcbiAgICAgKiBtYXAgY29udHJvbHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENhbnZhc0NvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYW52YXNDb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgTWFwJ3MgY2FudmFzIGFzIGFuIEhUTUwgY2FudmFzXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fSBjYW52YXNcbiAgICAgKi9cbiAgICBnZXRDYW52YXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FudmFzLmdldEVsZW1lbnQoKTtcbiAgICB9LFxuXG4gICAgX3NldHVwQ29udGFpbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGlkID0gdGhpcy5vcHRpb25zLmNvbnRhaW5lcjtcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xuICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtbWFwJyk7XG5cbiAgICAgICAgdmFyIGNhbnZhc0NvbnRhaW5lciA9IHRoaXMuX2NhbnZhc0NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jYW52YXMtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgY2FudmFzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWludGVyYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2FudmFzID0gbmV3IENhbnZhcyh0aGlzLCBjYW52YXNDb250YWluZXIpO1xuXG4gICAgICAgIHZhciBjb250cm9sQ29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWNvbnRyb2wtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgdmFyIGNvcm5lcnMgPSB0aGlzLl9jb250cm9sQ29ybmVycyA9IHt9O1xuICAgICAgICBbJ3RvcC1sZWZ0JywgJ3RvcC1yaWdodCcsICdib3R0b20tbGVmdCcsICdib3R0b20tcmlnaHQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIGNvcm5lcnNbcG9zXSA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jdHJsLScgKyBwb3MsIGNvbnRyb2xDb250YWluZXIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgX3NldHVwUGFpbnRlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnbCA9IHRoaXMuX2NhbnZhcy5nZXRXZWJHTENvbnRleHQoe1xuICAgICAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogdGhpcy5vcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQsXG4gICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRoaXMub3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXJcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFnbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0wnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFpbnRlciA9IG5ldyBQYWludGVyKGdsLCB0aGlzLnRyYW5zZm9ybSk7XG4gICAgfSxcblxuICAgIF9jb250ZXh0TG9zdDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIGJyb3dzZXIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRleHRSZXN0b3JlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJcyB0aGlzIG1hcCBmdWxseSBsb2FkZWQ/IElmIHRoZSBzdHlsZSBpc24ndCBsb2FkZWRcbiAgICAgKiBvciBpdCBoYXMgYSBjaGFuZ2UgdG8gdGhlIHNvdXJjZXMgb3Igc3R5bGUgdGhhdCBpc24ndFxuICAgICAqIHByb3BhZ2F0ZWQgdG8gaXRzIHN0eWxlLCByZXR1cm4gZmFsc2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gd2hldGhlciB0aGUgbWFwIGlzIGxvYWRlZFxuICAgICAqL1xuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHlsZURpcnR5IHx8IHRoaXMuX3NvdXJjZXNEaXJ0eSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUgJiYgIXRoaXMuc3R5bGUubG9hZGVkKCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhpcyBtYXAncyBzdHlsZSBhbmQgcmUtcmVuZGVyIHRoZSBtYXAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdXBkYXRlU3R5bGUgbmV3IHN0eWxlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXBkYXRlU3R5bGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0eWxlKSByZXR1cm4gdGhpcztcblxuICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gdGhpcy5fc3R5bGVEaXJ0eSB8fCB1cGRhdGVTdHlsZTtcbiAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHdoZW4gYSAocmUtKXJlbmRlciBvZiB0aGUgbWFwIGlzIHJlcXVpcmVkLCBlLmcuIHdoZW4gdGhlXG4gICAgICogdXNlciBwYW5uZWQgb3Igem9vbWVkLGYgb3IgbmV3IGRhdGEgaXMgYXZhaWxhYmxlLlxuICAgICAqIEByZXR1cm5zIHtNYXB9IHRoaXNcbiAgICAgKi9cbiAgICByZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiB0aGlzLl9zdHlsZURpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnN0eWxlLl9yZWNhbGN1bGF0ZSh0aGlzLnRyYW5zZm9ybS56b29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnN0eWxlICYmIHRoaXMuX3NvdXJjZXNEaXJ0eSAmJiAhdGhpcy5fc291cmNlc0RpcnR5VGltZW91dCkge1xuICAgICAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSwgNTApO1xuICAgICAgICAgICAgdGhpcy5zdHlsZS5fdXBkYXRlU291cmNlcyh0aGlzLnRyYW5zZm9ybSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhaW50ZXIucmVuZGVyKHRoaXMuc3R5bGUsIHtcbiAgICAgICAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxuICAgICAgICAgICAgdmVydGljZXM6IHRoaXMudmVydGljZXMsXG4gICAgICAgICAgICByb3RhdGluZzogdGhpcy5yb3RhdGluZyxcbiAgICAgICAgICAgIHpvb21pbmc6IHRoaXMuem9vbWluZ1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmZpcmUoJ3JlbmRlcicpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRlZCgpICYmICF0aGlzLl9sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2ZyYW1lSWQgPSBudWxsO1xuXG4gICAgICAgIGlmICghdGhpcy5hbmltYXRpb25Mb29wLnN0b3BwZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fc291cmNlc0RpcnR5IHx8IHRoaXMuX3JlcGFpbnQgfHwgIXRoaXMuYW5pbWF0aW9uTG9vcC5zdG9wcGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRGVzdHJveXMgdGhlIG1hcCdzIHVuZGVybHlpbmcgcmVzb3VyY2VzLCBpbmNsdWRpbmcgd2ViIHdvcmtlcnMuXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYXNoKSB0aGlzLl9oYXNoLnJlbW92ZSgpO1xuICAgICAgICBicm93c2VyLmNhbmNlbEZyYW1lKHRoaXMuX2ZyYW1lSWQpO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fc291cmNlc0RpcnR5VGltZW91dCk7XG4gICAgICAgIHRoaXMuc2V0U3R5bGUobnVsbCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcmVyZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiAhdGhpcy5fZnJhbWVJZCkge1xuICAgICAgICAgICAgdGhpcy5fZnJhbWVJZCA9IGJyb3dzZXIuZnJhbWUodGhpcy5yZW5kZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU3R5bGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3N0eWxlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU291cmNlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy5maXJlKGUudHlwZSwgdXRpbC5leHRlbmQoe3N0eWxlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgX2ZvcndhcmRMYXllckV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkVGlsZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9vblN0eWxlTG9hZDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLnN0eWxlLl9jYXNjYWRlKHRoaXMuX2NsYXNzZXMsIHt0cmFuc2l0aW9uOiBmYWxzZX0pO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU3R5bGVDaGFuZ2U6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGUodHJ1ZSk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTdHlsZUV2ZW50KGUpO1xuICAgIH0sXG5cbiAgICBfb25Tb3VyY2VBZGQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGUuc291cmNlO1xuICAgICAgICBpZiAoc291cmNlLm9uQWRkKVxuICAgICAgICAgICAgc291cmNlLm9uQWRkKHRoaXMpO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQoZSk7XG4gICAgfSxcblxuICAgIF9vblNvdXJjZVJlbW92ZTogZnVuY3Rpb24oZSkge1xuICAgICAgICB2YXIgc291cmNlID0gZS5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2Uub25SZW1vdmUpXG4gICAgICAgICAgICBzb3VyY2Uub25SZW1vdmUodGhpcyk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU291cmNlVXBkYXRlOiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9XG59KTtcblxudXRpbC5leHRlbmRBbGwoTWFwLnByb3RvdHlwZSwge1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlIGRlYnVnZ2luZyBtb2RlXG4gICAgICpcbiAgICAgKiBAbmFtZSBkZWJ1Z1xuICAgICAqIEBtZW1iZXJvZiBNYXBcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfZGVidWc6IGZhbHNlLFxuICAgIGdldCBkZWJ1ZygpIHsgcmV0dXJuIHRoaXMuX2RlYnVnOyB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkgeyB0aGlzLl9kZWJ1ZyA9IHZhbHVlOyB0aGlzLnVwZGF0ZSgpOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2hvdyBjb2xsaXNpb24gYm94ZXM6IHVzZWZ1bCBmb3IgZGVidWdnaW5nIGxhYmVsIHBsYWNlbWVudFxuICAgICAqIGluIHN0eWxlcy5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbGxpc2lvbkRlYnVnXG4gICAgICogQG1lbWJlcm9mIE1hcFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIF9jb2xsaXNpb25EZWJ1ZzogZmFsc2UsXG4gICAgZ2V0IGNvbGxpc2lvbkRlYnVnKCkgeyByZXR1cm4gdGhpcy5fY29sbGlzaW9uRGVidWc7IH0sXG4gICAgc2V0IGNvbGxpc2lvbkRlYnVnKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbGxpc2lvbkRlYnVnID0gdmFsdWU7XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHlsZS5zb3VyY2VzW2ldLnJlbG9hZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3R5bGUuc291cmNlc1tpXS5yZWxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBFbmFibGUgY29udGludW91cyByZXBhaW50IHRvIGFuYWx5emUgcGVyZm9ybWFuY2VcbiAgICAgKlxuICAgICAqIEBuYW1lIHJlcGFpbnRcbiAgICAgKiBAbWVtYmVyb2YgTWFwXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3JlcGFpbnQ6IGZhbHNlLFxuICAgIGdldCByZXBhaW50KCkgeyByZXR1cm4gdGhpcy5fcmVwYWludDsgfSxcbiAgICBzZXQgcmVwYWludCh2YWx1ZSkgeyB0aGlzLl9yZXBhaW50ID0gdmFsdWU7IHRoaXMudXBkYXRlKCk7IH0sXG5cbiAgICAvLyBzaG93IHZlcnRpY2VzXG4gICAgX3ZlcnRpY2VzOiBmYWxzZSxcbiAgICBnZXQgdmVydGljZXMoKSB7IHJldHVybiB0aGlzLl92ZXJ0aWNlczsgfSxcbiAgICBzZXQgdmVydGljZXModmFsdWUpIHsgdGhpcy5fdmVydGljZXMgPSB2YWx1ZTsgdGhpcy51cGRhdGUoKTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9wdXA7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgcG9wdXAgY29tcG9uZW50XG4gKiBAY2xhc3MgUG9wdXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuY2xvc2VCdXR0b25cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gb3B0aW9ucy5jbG9zZU9uQ2xpY2tcbiAqIEBleGFtcGxlXG4gKiB2YXIgdG9vbHRpcCA9IG5ldyBtYXBib3hnbC5Qb3B1cCgpXG4gKiAgIC5zZXRMYXRMbmcobWFwLnVucHJvamVjdChlLnBvaW50KSlcbiAqICAgLnNldEhUTUwoXCI8aDE+SGVsbG8gV29ybGQhPC9oMT5cIilcbiAqICAgLmFkZFRvKG1hcCk7XG4gKi9cbmZ1bmN0aW9uIFBvcHVwKG9wdGlvbnMpIHtcbiAgICB1dGlsLnNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ191cGRhdGVQb3NpdGlvbicsXG4gICAgICAgICdfb25DbGlja0Nsb3NlJ10sXG4gICAgICAgIHRoaXMpO1xufVxuXG5Qb3B1cC5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwgLyoqIEBsZW5kcyBQb3B1cC5wcm90b3R5cGUgKi97XG4gICAgb3B0aW9uczoge1xuICAgICAgICBjbG9zZUJ1dHRvbjogdHJ1ZSxcbiAgICAgICAgY2xvc2VPbkNsaWNrOiB0cnVlXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIHRoZSBwb3B1cCB0byBhIG1hcFxuICAgICAqIEBwYXJhbSB7TWFwfSBtYXBcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmUnLCB0aGlzLl91cGRhdGVQb3NpdGlvbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5fb25DbGlja0Nsb3NlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHBvcHVwIGZyb20gdGhlIG1hcFxuICAgICAqIEBleGFtcGxlXG4gICAgICogdmFyIHBvcHVwID0gbmV3IG1hcGJveGdsLlBvcHVwKCkuYWRkVG8obWFwKTtcbiAgICAgKiBwb3B1cC5yZW1vdmUoKTtcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbWFwKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlJywgdGhpcy5fdXBkYXRlUG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy5fbWFwLm9mZignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX21hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgY29vcmRpbmF0ZXMgb2YgcG9wdXAgZWxlbWVudCByZWxhdGl2ZSB0byBtYXBcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfVxuICAgICAqL1xuICAgIGdldExhdExuZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYXRMbmc7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY29vcmRpbmF0ZXMgb2YgYSBwb3B1cCBlbGVtZW50IHRvIGEgbWFwXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtQb3B1cH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF0TG5nOiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdGhpcy5fbGF0TG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIHRleHQgb25seSBjb250ZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHNldFRleHQ6IGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgdGhpcy5fY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIEhUTUwgY29udGVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRIVE1MOiBmdW5jdGlvbihodG1sKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgICAgICAgdmFyIHRlbXAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib2R5JyksIGNoaWxkO1xuICAgICAgICB0ZW1wLmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjaGlsZCA9IHRlbXAuZmlyc3RDaGlsZDtcbiAgICAgICAgICAgIGlmICghY2hpbGQpIGJyZWFrO1xuICAgICAgICAgICAgdGhpcy5fY29udGVudC5hcHBlbmRDaGlsZChjaGlsZCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1wb3B1cCcsIHRoaXMuX21hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgICAgIHRoaXMuX3RpcCAgICAgPSBET00uY3JlYXRlKCdkaXYnLCAnbWFwYm94Z2wtcG9wdXAtdGlwJywgICAgIHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgICAgICB0aGlzLl93cmFwcGVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLXBvcHVwLWNvbnRlbnQnLCB0aGlzLl9jb250YWluZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNsb3NlQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24gPSBET00uY3JlYXRlKCdidXR0b24nLCAnbWFwYm94Z2wtcG9wdXAtY2xvc2UtYnV0dG9uJywgdGhpcy5fd3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uaW5uZXJIVE1MID0gJyYjMjE1Oyc7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGVudCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlQ29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fY29udGVudCB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fd3JhcHBlcjtcblxuICAgICAgICB3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICAgICAgICAgIG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGhpcy5fY2xvc2VCdXR0b24pO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2xhdExuZyB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBwb3MgPSB0aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sYXRMbmcpLnJvdW5kKCksXG4gICAgICAgICAgICBhbmNob3IgPSB0aGlzLm9wdGlvbnMuYW5jaG9yO1xuXG4gICAgICAgIGlmICghYW5jaG9yKSB7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgaWYgKHBvcy55IDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gWyd0b3AnXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9zLnkgPiB0aGlzLl9tYXAudHJhbnNmb3JtLmhlaWdodCAtIGhlaWdodCkge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFsnYm90dG9tJ107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocG9zLnggPCB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgnbGVmdCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwb3MueCA+IHRoaXMuX21hcC50cmFuc2Zvcm0ud2lkdGggLSB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgncmlnaHQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFuY2hvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBhbmNob3IgPSAnYm90dG9tJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gYW5jaG9yLmpvaW4oJy0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFuY2hvciA9IGFuY2hvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhbmNob3JUcmFuc2xhdGUgPSB7XG4gICAgICAgICAgICAndG9wJzogJ3RyYW5zbGF0ZSgtNTAlLDApJyxcbiAgICAgICAgICAgICd0b3AtbGVmdCc6ICd0cmFuc2xhdGUoMCwwKScsXG4gICAgICAgICAgICAndG9wLXJpZ2h0JzogJ3RyYW5zbGF0ZSgtMTAwJSwwKScsXG4gICAgICAgICAgICAnYm90dG9tJzogJ3RyYW5zbGF0ZSgtNTAlLC0xMDAlKScsXG4gICAgICAgICAgICAnYm90dG9tLWxlZnQnOiAndHJhbnNsYXRlKDAsLTEwMCUpJyxcbiAgICAgICAgICAgICdib3R0b20tcmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC0xMDAlKScsXG4gICAgICAgICAgICAnbGVmdCc6ICd0cmFuc2xhdGUoMCwtNTAlKScsXG4gICAgICAgICAgICAncmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC01MCUpJ1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0O1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gYW5jaG9yVHJhbnNsYXRlKSB7XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1wb3B1cC1hbmNob3ItJyArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtcG9wdXAtYW5jaG9yLScgKyBhbmNob3IpO1xuXG4gICAgICAgIERPTS5zZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCBhbmNob3JUcmFuc2xhdGVbYW5jaG9yXSArICcgdHJhbnNsYXRlKCcgKyBwb3MueCArICdweCwnICsgcG9zLnkgKyAncHgpJyk7XG4gICAgfSxcblxuICAgIF9vbkNsaWNrQ2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFjdG9yO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHRoZSBbQWN0b3IgZGVzaWduIHBhdHRlcm5dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWN0b3JfbW9kZWwpXG4gKiB0aGF0IG1haW50YWlucyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYXN5bmNocm9ub3VzIHRhc2tzIGFuZCB0aGUgb2JqZWN0c1xuICogdGhhdCBzcGluIHRoZW0gb2ZmIC0gaW4gdGhpcyBjYXNlLCB0YXNrcyBsaWtlIHBhcnNpbmcgcGFydHMgb2Ygc3R5bGVzLFxuICogb3duZWQgYnkgdGhlIHN0eWxlc1xuICpcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSB0YXJnZXRcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSBwYXJlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEFjdG9yKHRhcmdldCwgcGFyZW50KSB7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5jYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLmNhbGxiYWNrSUQgPSAwO1xuICAgIHRoaXMucmVjZWl2ZSA9IHRoaXMucmVjZWl2ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0aGlzLnJlY2VpdmUsIGZhbHNlKTtcbn1cblxuQWN0b3IucHJvdG90eXBlLnJlY2VpdmUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG4gICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGEsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJzxyZXNwb25zZT4nKSB7XG4gICAgICAgIGNhbGxiYWNrID0gdGhpcy5jYWxsYmFja3NbZGF0YS5pZF07XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tkYXRhLmlkXTtcbiAgICAgICAgY2FsbGJhY2soZGF0YS5lcnJvciB8fCBudWxsLCBkYXRhLmRhdGEpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEuaWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBpZCA9IGRhdGEuaWQ7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhLCBmdW5jdGlvbihlcnIsIGRhdGEsIGJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIHRoaXMucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICc8cmVzcG9uc2U+JyxcbiAgICAgICAgICAgICAgICBpZDogU3RyaW5nKGlkKSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID8gU3RyaW5nKGVycikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGFcbiAgICAgICAgICAgIH0sIGJ1ZmZlcnMpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhKTtcbiAgICB9XG59O1xuXG5BY3Rvci5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCBidWZmZXJzKSB7XG4gICAgdmFyIGlkID0gbnVsbDtcbiAgICBpZiAoY2FsbGJhY2spIHRoaXMuY2FsbGJhY2tzW2lkID0gdGhpcy5jYWxsYmFja0lEKytdID0gY2FsbGJhY2s7XG4gICAgdGhpcy5wb3N0TWVzc2FnZSh7IHR5cGU6IHR5cGUsIGlkOiBTdHJpbmcoaWQpLCBkYXRhOiBkYXRhIH0sIGJ1ZmZlcnMpO1xufTtcblxuLyoqXG4gKiBXcmFwcGVkIHBvc3RNZXNzYWdlIEFQSSB0aGF0IGFic3RyYWN0cyBhcm91bmQgSUUncyBsYWNrIG9mXG4gKiBgdHJhbnNmZXJMaXN0YCBzdXBwb3J0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmZXJMaXN0XG4gKi9cbkFjdG9yLnByb3RvdHlwZS5wb3N0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCkge1xuICAgIHRyeSB7XG4gICAgICAgIHRoaXMudGFyZ2V0LnBvc3RNZXNzYWdlKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLnRhcmdldC5wb3N0TWVzc2FnZShtZXNzYWdlKTsgLy8gTm8gc3VwcG9ydCBmb3IgdHJhbnNmZXJMaXN0IG9uIElFXG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5nZXRKU09OID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTtcbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgY2FsbGJhY2soZSk7XG4gICAgfTtcbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh4aHIuc3RhdHVzID49IDIwMCAmJiB4aHIuc3RhdHVzIDwgMzAwICYmIHhoci5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0QXJyYXlCdWZmZXIgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpO1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oZSkge1xuICAgICAgICBjYWxsYmFjayhlKTtcbiAgICB9O1xuICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCAzMDAgJiYgeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCB4aHIucmVzcG9uc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0SW1hZ2UgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgIGltZy5jcm9zc09yaWdpbiA9ICdBbm9ueW1vdXMnO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgaW1nKTtcbiAgICB9O1xuICAgIGltZy5zcmMgPSB1cmw7XG4gICAgaW1nLmdldERhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBpbWcud2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWcuaGVpZ2h0O1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIDAsIDApO1xuICAgICAgICByZXR1cm4gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW1nLndpZHRoLCBpbWcuaGVpZ2h0KS5kYXRhO1xuICAgIH07XG4gICAgcmV0dXJuIGltZztcbn07XG5cbmV4cG9ydHMuZ2V0VmlkZW8gPSBmdW5jdGlvbih1cmxzLCBjYWxsYmFjaykge1xuICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgdmlkZW8uY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICB2aWRlby5vbmxvYWRzdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCB2aWRlbyk7XG4gICAgfTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzb3VyY2UnKTtcbiAgICAgICAgcy5zcmMgPSB1cmxzW2ldO1xuICAgICAgICB2aWRlby5hcHBlbmRDaGlsZChzKTtcbiAgICB9XG4gICAgdmlkZW8uZ2V0RGF0YSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdmlkZW87IH07XG4gICAgcmV0dXJuIHZpZGVvO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENhbnZhcyA9IHJlcXVpcmUoJy4vY2FudmFzJyk7XG5cbnZhciBmcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5mcmFtZSA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgcmV0dXJuIGZyYW1lKGZuKTtcbn07XG5cbnZhciBjYW5jZWwgPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNDYW5jZWxBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5jYW5jZWxGcmFtZSA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgY2FuY2VsKGlkKTtcbn07XG5cbmV4cG9ydHMudGltZWQgPSBmdW5jdGlvbiAoZm4sIGR1ciwgY3R4KSB7XG4gICAgaWYgKCFkdXIpIHtcbiAgICAgICAgZm4uY2FsbChjdHgsIDEpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYWJvcnQgPSBmYWxzZSxcbiAgICAgICAgc3RhcnQgPSB3aW5kb3cucGVyZm9ybWFuY2UgPyB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdygpO1xuXG4gICAgZnVuY3Rpb24gdGljayhub3cpIHtcbiAgICAgICAgaWYgKGFib3J0KSByZXR1cm47XG4gICAgICAgIGlmICghd2luZG93LnBlcmZvcm1hbmNlKSBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIGlmIChub3cgPj0gc3RhcnQgKyBkdXIpIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAobm93IC0gc3RhcnQpIC8gZHVyKTtcbiAgICAgICAgICAgIGV4cG9ydHMuZnJhbWUodGljayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBleHBvcnRzLmZyYW1lKHRpY2spO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyBhYm9ydCA9IHRydWU7IH07XG59O1xuXG4vKipcbiAqIFRlc3Qgd2hldGhlciB0aGUgYmFzaWMgSmF2YVNjcmlwdCBhbmQgRE9NIGZlYXR1cmVzIHJlcXVpcmVkIGZvciBNYXBib3ggR0wgYXJlIHByZXNlbnQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0PWZhbHNlXSBJZiBgdHJ1ZWAsIG1hcCBjcmVhdGlvbiB3aWxsIGZhaWwgaWYgdGhlIGltcGxlbWVudGF0aW9uIGRldGVybWluZXMgdGhhdCB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGNyZWF0ZWQgV2ViR0wgY29udGV4dCB3b3VsZCBiZSBkcmFtYXRpY2FsbHkgbG93ZXIgdGhhbiBleHBlY3RlZC5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBNYXBib3ggR0wgc2hvdWxkIGJlIGV4cGVjdGVkIHRvIHdvcmssIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cbmV4cG9ydHMuc3VwcG9ydGVkID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gICAgdmFyIHN1cHBvcnRzID0gW1xuXG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7IH0sXG5cbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnOyB9LFxuXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShBcnJheS5wcm90b3R5cGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZXZlcnkgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZmlsdGVyICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2ggJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5tYXAgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc29tZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2UgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucmVkdWNlUmlnaHQgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShGdW5jdGlvbi5wcm90b3R5cGUgJiYgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpICYmXG4gICAgICAgICAgICAgICAgISEoT2JqZWN0LmtleXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmNyZWF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmlzU2VhbGVkICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5pc0Zyb3plbiAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuaXNFeHRlbnNpYmxlICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5zZWFsICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAnSlNPTicgaW4gd2luZG93ICYmICdwYXJzZScgaW4gSlNPTiAmJiAnc3RyaW5naWZ5JyBpbiBKU09OO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDYW52YXMoKS5zdXBwb3J0c1dlYkdMQ29udGV4dCgob3B0aW9ucyAmJiBvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpIHx8IGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuICdXb3JrZXInIGluIHdpbmRvdzsgfVxuICAgIF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1cHBvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghc3VwcG9ydHNbaV0oKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydHMuaGFyZHdhcmVDb25jdXJyZW5jeSA9IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5IHx8IDg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGV2aWNlUGl4ZWxSYXRpbycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYW52YXM7XG5cbmZ1bmN0aW9uIENhbnZhcyhwYXJlbnQsIGNvbnRhaW5lcikge1xuICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG5cbiAgICBpZiAocGFyZW50ICYmIGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgIHRoaXMuY2FudmFzLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWNhbnZhcycpO1xuICAgICAgICB0aGlzLmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgcGFyZW50Ll9jb250ZXh0TG9zdC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0cmVzdG9yZWQnLCBwYXJlbnQuX2NvbnRleHRSZXN0b3JlZC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIDApO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgIH1cbn1cblxuQ2FudmFzLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgLy8gUmVxdWVzdCB0aGUgcmVxdWlyZWQgY2FudmFzIHNpemUgdGFraW5nIHRoZSBwaXhlbHJhdGlvIGludG8gYWNjb3VudC5cbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHBpeGVsUmF0aW8gKiB3aWR0aDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBwaXhlbFJhdGlvICogaGVpZ2h0O1xuXG4gICAgLy8gTWFpbnRhaW4gdGhlIHNhbWUgY2FudmFzIHNpemUsIHBvdGVudGlhbGx5IGRvd25zY2FsaW5nIGl0IGZvciBIaURQSSBkaXNwbGF5c1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG59O1xuXG52YXIgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyA9IHtcbiAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgIGFscGhhOiB0cnVlLFxuICAgIHN0ZW5jaWw6IHRydWUsXG4gICAgZGVwdGg6IGZhbHNlXG59O1xuXG5DYW52YXMucHJvdG90eXBlLmdldFdlYkdMQ29udGV4dCA9IGZ1bmN0aW9uKGF0dHJpYnV0ZXMpIHtcbiAgICBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe30sIGF0dHJpYnV0ZXMsIHJlcXVpcmVkQ29udGV4dEF0dHJpYnV0ZXMpO1xuXG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldENvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG59O1xuXG5DYW52YXMucHJvdG90eXBlLnN1cHBvcnRzV2ViR0xDb250ZXh0ID0gZnVuY3Rpb24oZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe1xuICAgICAgICBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0OiBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0XG4gICAgfSwgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyk7XG5cbiAgICBpZiAoJ3Byb2JhYmx5U3VwcG9ydHNDb250ZXh0JyBpbiB0aGlzLmNhbnZhcykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXMucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0KCdleHBlcmltZW50YWwtd2ViZ2wnLCBhdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2UgaWYgKCdzdXBwb3J0c0NvbnRleHQnIGluIHRoaXMuY2FudmFzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhcy5zdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN1cHBvcnRzQ29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhd2luZG93LldlYkdMUmVuZGVyaW5nQ29udGV4dCAmJiAhIXRoaXMuZ2V0V2ViR0xDb250ZXh0KGZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpO1xufTtcblxuQ2FudmFzLnByb3RvdHlwZS5nZXRFbGVtZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFjdG9yID0gcmVxdWlyZSgnLi4vYWN0b3InKTtcbnZhciBXZWJXb3JraWZ5ID0gcmVxdWlyZSgnd2Vid29ya2lmeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERpc3BhdGNoZXI7XG5cbmZ1bmN0aW9uIERpc3BhdGNoZXIobGVuZ3RoLCBwYXJlbnQpIHtcbiAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIHRoaXMuY3VycmVudEFjdG9yID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB3b3JrZXIgPSBuZXcgV2ViV29ya2lmeShyZXF1aXJlKCcuLi8uLi9zb3VyY2Uvd29ya2VyJykpO1xuICAgICAgICB2YXIgYWN0b3IgPSBuZXcgQWN0b3Iod29ya2VyLCBwYXJlbnQpO1xuICAgICAgICBhY3Rvci5uYW1lID0gXCJXb3JrZXIgXCIgKyBpO1xuICAgICAgICB0aGlzLmFjdG9ycy5wdXNoKGFjdG9yKTtcbiAgICB9XG59XG5cbkRpc3BhdGNoZXIucHJvdG90eXBlID0ge1xuICAgIGJyb2FkY2FzdDogZnVuY3Rpb24odHlwZSwgZGF0YSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmFjdG9yc1tpXS5zZW5kKHR5cGUsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNlbmQ6IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCB0YXJnZXRJRCwgYnVmZmVycykge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldElEICE9PSAnbnVtYmVyJyB8fCBpc05hTih0YXJnZXRJRCkpIHtcbiAgICAgICAgICAgIC8vIFVzZSByb3VuZCByb2JpbiB0byBzZW5kIHJlcXVlc3RzIHRvIHdlYiB3b3JrZXJzLlxuICAgICAgICAgICAgdGFyZ2V0SUQgPSB0aGlzLmN1cnJlbnRBY3RvciA9ICh0aGlzLmN1cnJlbnRBY3RvciArIDEpICUgdGhpcy5hY3RvcnMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hY3RvcnNbdGFyZ2V0SURdLnNlbmQodHlwZSwgZGF0YSwgY2FsbGJhY2ssIGJ1ZmZlcnMpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0SUQ7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuYWN0b3JzW2ldLnRhcmdldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24gKHRhZ05hbWUsIGNsYXNzTmFtZSwgY29udGFpbmVyKSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlbC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgaWYgKGNvbnRhaW5lcikgY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcbiAgICByZXR1cm4gZWw7XG59O1xuXG52YXIgZG9jU3R5bGUgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU7XG5cbmZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocHJvcHNbaV0gaW4gZG9jU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBwcm9wc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxudmFyIHNlbGVjdFByb3AgPSB0ZXN0UHJvcChbJ3VzZXJTZWxlY3QnLCAnTW96VXNlclNlbGVjdCcsICdXZWJraXRVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKSxcbiAgICB1c2VyU2VsZWN0O1xuZXhwb3J0cy5kaXNhYmxlRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc2VsZWN0UHJvcCkge1xuICAgICAgICB1c2VyU2VsZWN0ID0gZG9jU3R5bGVbc2VsZWN0UHJvcF07XG4gICAgICAgIGRvY1N0eWxlW3NlbGVjdFByb3BdID0gJ25vbmUnO1xuICAgIH1cbn07XG5leHBvcnRzLmVuYWJsZURyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGVjdFByb3ApIHtcbiAgICAgICAgZG9jU3R5bGVbc2VsZWN0UHJvcF0gPSB1c2VyU2VsZWN0O1xuICAgIH1cbn07XG5cbnZhciB0cmFuc2Zvcm1Qcm9wID0gdGVzdFByb3AoWyd0cmFuc2Zvcm0nLCAnV2Via2l0VHJhbnNmb3JtJ10pO1xuZXhwb3J0cy5zZXRUcmFuc2Zvcm0gPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBlbC5zdHlsZVt0cmFuc2Zvcm1Qcm9wXSA9IHZhbHVlO1xufTtcblxuLy8gU3VwcHJlc3MgdGhlIG5leHQgY2xpY2ssIGJ1dCBvbmx5IGlmIGl0J3MgaW1tZWRpYXRlLlxuZnVuY3Rpb24gc3VwcHJlc3NDbGljayhlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG59XG5leHBvcnRzLnN1cHByZXNzQ2xpY2sgPSBmdW5jdGlvbigpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzdXBwcmVzc0NsaWNrLCB0cnVlKTtcbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG4gICAgfSwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIVFRQX1VSTDogJ2h0dHA6Ly9hLnRpbGVzLm1hcGJveC5jb20nLFxuICAgIEhUVFBTX1VSTDogJ2h0dHBzOi8vYS50aWxlcy5tYXBib3guY29tJyxcbiAgICBGT1JDRV9IVFRQUzogdHJ1ZSxcbiAgICBSRVFVSVJFX0FDQ0VTU19UT0tFTjogdHJ1ZVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLyoqXG4gKiBNZXRob2RzIG1peGVkIGluIHRvIG90aGVyIGNsYXNzZXMgZm9yIGV2ZW50IGNhcGFiaWxpdGllcy5cbiAqIEBtaXhpbiBFdmVudGVkXG4gKi9cbnZhciBFdmVudGVkID0ge1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGEgc3BlY2lmaWVkIGV2ZW50IHdpdGggYSBsaXN0ZW5lciBmdW5jdGlvbiB0aGUgbGF0dGVyIGdldHMgdGhlIGRhdGEgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCB0byBgZmlyZWAgYW5kIGFkZGl0aW9uYWxseSBgdGFyZ2V0YCBhbmQgYHR5cGVgIHByb3BlcnRpZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbjogZnVuY3Rpb24odHlwZSwgZm4pIHtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSB0aGlzLl9ldmVudHNbdHlwZV0gfHwgW107XG4gICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGZuKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgZXZlbnQgbGlzdGVuZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBbdHlwZV0gRXZlbnQgdHlwZS4gSWYgbm9uZSBpcyBzcGVjaWZpZWQsIHJlbW92ZSBhbGwgbGlzdGVuZXJzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2xpc3RlbmVyXSBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQuIElmIG5vbmUgaXMgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgYXJlIHJlbW92ZWRcbiAgICAgKi9cbiAgICBvZmY6IGZ1bmN0aW9uKHR5cGUsIGZuKSB7XG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgICAgLy8gY2xlYXIgYWxsIGxpc3RlbmVycyBpZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMubGlzdGVucyh0eXBlKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGZuKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gdGhpcy5fZXZlbnRzW3R5cGVdLmluZGV4T2YoZm4pO1xuICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbCBhIGZ1bmN0aW9uIG9uY2Ugd2hlbiBhbiBldmVudCBoYXMgZmlyZWRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uY2Ugd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbmNlOiBmdW5jdGlvbih0eXBlLCBmbikge1xuICAgICAgICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMub2ZmKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICAgICAgZm4uY2FsbCh0aGlzLCBkYXRhKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLm9uKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRmlyZSBldmVudCBvZiBhIGdpdmVuIHN0cmluZyB0eXBlIHdpdGggdGhlIGdpdmVuIGRhdGEgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXZlbnQgbmFtZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV0gT3B0aW9uYWwgZGF0YSBwYXNzZWQgZG93biB0byB0aGUgZXZlbnQgb2JqZWN0XG4gICAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgb2JqZWN0IGxpc3RlbnMgdG8gYW4gZXZlbnQgb2YgYSBwYXJ0aWN1bGFyIHR5cGVcbiAgICAgKi9cbiAgICBmaXJlOiBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBkYXRhID0gdXRpbC5leHRlbmQoe30sIGRhdGEpO1xuICAgICAgICB1dGlsLmV4dGVuZChkYXRhLCB7dHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzfSk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmNhbGwodGhpcywgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYW4gZXZlbnQgaXMgcmVnaXN0ZXJlZCB0byBhIHR5cGVcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBvYmplY3QgbGlzdGVucyB0byBhbiBldmVudCBvZiBhIHBhcnRpY3VsYXIgdHlwZVxuICAgICAqL1xuICAgIGxpc3RlbnM6IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICEhKHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbdHlwZV0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRlZDtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaHM7XG5cbmZ1bmN0aW9uIEdseXBocyhwYmYsIGVuZCkge1xuICAgIHRoaXMuc3RhY2tzID0gcGJmLnJlYWRGaWVsZHMocmVhZEZvbnRzdGFja3MsIFtdLCBlbmQpO1xufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrcyh0YWcsIHN0YWNrcywgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkge1xuICAgICAgICB2YXIgZm9udHN0YWNrID0gcGJmLnJlYWRNZXNzYWdlKHJlYWRGb250c3RhY2ssIHtnbHlwaHM6IHt9fSk7XG4gICAgICAgIHN0YWNrcy5wdXNoKGZvbnRzdGFjayk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrKHRhZywgZm9udHN0YWNrLCBwYmYpIHtcbiAgICBpZiAodGFnID09PSAxKSBmb250c3RhY2submFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSAyKSBmb250c3RhY2sucmFuZ2UgPSBwYmYucmVhZFN0cmluZygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykge1xuICAgICAgICB2YXIgZ2x5cGggPSBwYmYucmVhZE1lc3NhZ2UocmVhZEdseXBoLCB7fSk7XG4gICAgICAgIGZvbnRzdGFjay5nbHlwaHNbZ2x5cGguaWRdID0gZ2x5cGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkR2x5cGgodGFnLCBnbHlwaCwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkgZ2x5cGguaWQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgZ2x5cGguYml0bWFwID0gcGJmLnJlYWRCeXRlcygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykgZ2x5cGgud2lkdGggPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgZ2x5cGguaGVpZ2h0ID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDUpIGdseXBoLmxlZnQgPSBwYmYucmVhZFNWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDYpIGdseXBoLnRvcCA9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNykgZ2x5cGguYWR2YW5jZSA9IHBiZi5yZWFkVmFyaW50KCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGU7XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKGEsIGIsIHQpIHtcbiAgICByZXR1cm4gKGEgKiAoMSAtIHQpKSArIChiICogdCk7XG59XG5cbmludGVycG9sYXRlLm51bWJlciA9IGludGVycG9sYXRlO1xuXG5pbnRlcnBvbGF0ZS52ZWMyID0gZnVuY3Rpb24oZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMV0sIHRvWzFdLCB0KVxuICAgIF07XG59O1xuXG4vKlxuICogSW50ZXJwb2xhdGUgYmV0d2VlbiB0d28gY29sb3JzIGdpdmVuIGFzIDQtZWxlbWVudCBhcnJheXMuXG4gKlxuICogQHBhcmFtIHtDb2xvcn0gZnJvbVxuICogQHBhcmFtIHtDb2xvcn0gdG9cbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gZmFjdG9yIGJldHdlZW4gMCBhbmQgMVxuICogQHJldHVybnMge0NvbG9yfSBpbnRlcnBvbGF0ZWQgY29sb3JcbiAqL1xuaW50ZXJwb2xhdGUuY29sb3IgPSBmdW5jdGlvbihmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMF0sIHRvWzBdLCB0KSxcbiAgICAgICAgaW50ZXJwb2xhdGUoZnJvbVsxXSwgdG9bMV0sIHQpLFxuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzJdLCB0b1syXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bM10sIHRvWzNdLCB0KVxuICAgIF07XG59O1xuXG5pbnRlcnBvbGF0ZS5hcnJheSA9IGZ1bmN0aW9uKGZyb20sIHRvLCB0KSB7XG4gICAgcmV0dXJuIGZyb20ubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlKGQsIHRvW2ldLCB0KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuL2Jyb3dzZXInKTtcblxuZnVuY3Rpb24gbm9ybWFsaXplVVJMKHVybCwgcGF0aFByZWZpeCwgYWNjZXNzVG9rZW4pIHtcbiAgICBhY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuIHx8IGNvbmZpZy5BQ0NFU1NfVE9LRU47XG5cbiAgICBpZiAoIWFjY2Vzc1Rva2VuICYmIGNvbmZpZy5SRVFVSVJFX0FDQ0VTU19UT0tFTikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FuIEFQSSBhY2Nlc3MgdG9rZW4gaXMgcmVxdWlyZWQgdG8gdXNlIE1hcGJveCBHTC4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZGV2ZWxvcGVycy9hcGkvI2FjY2Vzcy10b2tlbnMnKTtcbiAgICB9XG5cbiAgICB2YXIgaHR0cHMgPSBjb25maWcuRk9SQ0VfSFRUUFMgfHxcbiAgICAgICAgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonKTtcblxuICAgIHVybCA9IHVybC5yZXBsYWNlKC9ebWFwYm94OlxcL1xcLy8sIChodHRwcyA/IGNvbmZpZy5IVFRQU19VUkwgOiBjb25maWcuSFRUUF9VUkwpICsgcGF0aFByZWZpeCk7XG4gICAgdXJsICs9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyZhY2Nlc3NfdG9rZW49JyA6ICc/YWNjZXNzX3Rva2VuPSc7XG5cbiAgICBpZiAoY29uZmlnLlJFUVVJUkVfQUNDRVNTX1RPS0VOKSB7XG4gICAgICAgIGlmIChhY2Nlc3NUb2tlblswXSA9PT0gJ3MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VzZSBhIHB1YmxpYyBhY2Nlc3MgdG9rZW4gKHBrLiopIHdpdGggTWFwYm94IEdMIEpTLCBub3QgYSBzZWNyZXQgYWNjZXNzIHRva2VuIChzay4qKS4gJyArXG4gICAgICAgICAgICAgICAgJ1NlZSBodHRwczovL3d3dy5tYXBib3guY29tL2RldmVsb3BlcnMvYXBpLyNhY2Nlc3MtdG9rZW5zJyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cmwgKz0gYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybDtcbn1cblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU3R5bGVVUkwgPSBmdW5jdGlvbih1cmwsIGFjY2Vzc1Rva2VuKSB7XG4gICAgdmFyIHVzZXIgPSB1cmwubWF0Y2goL15tYXBib3g6XFwvXFwvKFteLl0rKS8pO1xuICAgIGlmICghdXNlcilcbiAgICAgICAgcmV0dXJuIHVybDtcblxuICAgIHJldHVybiBub3JtYWxpemVVUkwodXJsLCAnL3N0eWxlcy92MS8nICsgdXNlclsxXSArICcvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU291cmNlVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgdXJsID0gbm9ybWFsaXplVVJMKHVybCArICcuanNvbicsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xuXG4gICAgLy8gVGlsZUpTT04gcmVxdWVzdHMgbmVlZCBhIHNlY3VyZSBmbGFnIGFwcGVuZGVkIHRvIHRoZWlyIFVSTHMgc29cbiAgICAvLyB0aGF0IHRoZSBzZXJ2ZXIga25vd3MgdG8gc2VuZCBTU0wtaWZpZWQgcmVzb3VyY2UgcmVmZXJlbmNlcy5cbiAgICBpZiAodXJsLmluZGV4T2YoJ2h0dHBzJykgPT09IDApXG4gICAgICAgIHVybCArPSAnJnNlY3VyZSc7XG5cbiAgICByZXR1cm4gdXJsO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplR2x5cGhzVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZVVSTCh1cmwsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplVGlsZVVSTCA9IGZ1bmN0aW9uKHVybCwgc291cmNlVXJsKSB7XG4gICAgaWYgKCFzb3VyY2VVcmwgfHwgIXNvdXJjZVVybC5tYXRjaCgvXm1hcGJveDpcXC9cXC8vKSlcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICByZXR1cm4gdXJsLnJlcGxhY2UoL1xcLigoPzpwbmd8anBnKVxcZCopKD89JHxcXD8pLywgYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID49IDIgPyAnQDJ4LiQxJyA6ICcuJDEnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBBIFttb3N0LXJlY2VudGx5LXVzZWQgY2FjaGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FjaGVfYWxnb3JpdGhtcylcbiAqIHdpdGggaGFzaCBsb29rdXAgbWFkZSBwb3NzaWJsZSBieSBrZWVwaW5nIGEgbGlzdCBvZiBrZXlzIGluIHBhcmFsbGVsIHRvXG4gKiBhbiBhcnJheSBvZiBkaWN0aW9uYXJ5IG9mIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXggbnVtYmVyIG9mIHBlcm1pdHRlZCB2YWx1ZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVtb3ZlIGNhbGxiYWNrIGNhbGxlZCB3aXRoIGl0ZW1zIHdoZW4gdGhleSBleHBpcmVcbiAqIEBwcml2YXRlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gTVJVQ2FjaGU7XG5mdW5jdGlvbiBNUlVDYWNoZShtYXgsIG9uUmVtb3ZlKSB7XG4gICAgdGhpcy5tYXggPSBtYXg7XG4gICAgdGhpcy5vblJlbW92ZSA9IG9uUmVtb3ZlO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cblxuLyoqXG4gKiBDbGVhciB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7TVJVQ2FjaGV9IHRoaXMgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMubGlzdCkge1xuICAgICAgICB0aGlzLm9uUmVtb3ZlKHRoaXMubGlzdFtrZXldKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpc3QgPSB7fTtcbiAgICB0aGlzLm9yZGVyID0gW107XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBBZGQgYSBrZXksIHZhbHVlIGNvbWJpbmF0aW9uIHRvIHRoZSBjYWNoZSwgdHJpbW1pbmcgaXRzIHNpemUgaWYgdGhpcyBwdXNoZXNcbiAqIGl0IG92ZXIgbWF4IGxlbmd0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IGxvb2t1cCBrZXkgZm9yIHRoZSBpdGVtXG4gKiBAcGFyYW0geyp9IGRhdGEgYW55IHZhbHVlXG4gKlxuICogQHJldHVybnMge01SVUNhY2hlfSB0aGlzIGNhY2hlXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB0aGlzLmxpc3Rba2V5XSA9IGRhdGE7XG4gICAgdGhpcy5vcmRlci5wdXNoKGtleSk7XG5cbiAgICBpZiAodGhpcy5vcmRlci5sZW5ndGggPiB0aGlzLm1heCkge1xuICAgICAgICB2YXIgcmVtb3ZlZERhdGEgPSB0aGlzLmdldCh0aGlzLm9yZGVyWzBdKTtcbiAgICAgICAgaWYgKHJlbW92ZWREYXRhKSB0aGlzLm9uUmVtb3ZlKHJlbW92ZWREYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYGtleWAgaXMgcHJlc2VudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBiZSBsb29rZWQtdXBcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIHRoZSBjYWNoZSBoYXMgdGhpcyB2YWx1ZVxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmxpc3Q7XG59O1xuXG4vKlxuICogTGlzdCBhbGwga2V5cyBpbiB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gYW4gYXJyYXkgb2Yga2V5cyBpbiB0aGlzIGNhY2hlLlxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm9yZGVyO1xufTtcblxuLypcbiAqIEdldCB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYSBzcGVjaWZpYyBrZXkuIElmIHRoZSBrZXkgaXMgbm90IGZvdW5kLFxuICogcmV0dXJucyBgbnVsbGBcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gbG9vayB1cFxuICogQHJldHVybnMgeyp9IHRoZSBkYXRhLCBvciBudWxsIGlmIGl0IGlzbid0IGZvdW5kXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsgcmV0dXJuIG51bGw7IH1cblxuICAgIHZhciBkYXRhID0gdGhpcy5saXN0W2tleV07XG5cbiAgICBkZWxldGUgdGhpcy5saXN0W2tleV07XG4gICAgdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGtleSksIDEpO1xuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUb2tlbnM7XG5cbi8qKlxuICogUmVwbGFjZSB0b2tlbnMgaW4gYSBzdHJpbmcgdGVtcGxhdGUgd2l0aCB2YWx1ZXMgaW4gYW4gb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgYSBrZXkvdmFsdWUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9rZW5zIGFuZCByZXBsYWNlbWVudHNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IHRoZSB0ZW1wbGF0ZSBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0ZW1wbGF0ZSB3aXRoIHRva2VucyByZXBsYWNlZFxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVRva2Vucyhwcm9wZXJ0aWVzLCB0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgveyhbXnt9KClcXFtcXF08PiQ9OjsuLF5dKyl9L2csIGZ1bmN0aW9uKG1hdGNoLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSBpbiBwcm9wZXJ0aWVzID8gcHJvcGVydGllc1trZXldIDogJyc7XG4gICAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBVbml0QmV6aWVyID0gcmVxdWlyZSgndW5pdGJlemllcicpO1xuXG4vKipcbiAqIEdpdmVuIGEgdmFsdWUgYHRgIHRoYXQgdmFyaWVzIGJldHdlZW4gMCBhbmQgMSwgcmV0dXJuXG4gKiBhbiBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uIHRoYXQgZWFzZXMgYmV0d2VlbiAwIGFuZCAxIGluIGEgcGxlYXNpbmdcbiAqIGN1YmljIGluLW91dCBmYXNoaW9uLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IGlucHV0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBpbnB1dFxuICovXG5leHBvcnRzLmVhc2VDdWJpY0luT3V0ID0gZnVuY3Rpb24gKHQpIHtcbiAgICBpZiAodCA8PSAwKSByZXR1cm4gMDtcbiAgICBpZiAodCA+PSAxKSByZXR1cm4gMTtcbiAgICB2YXIgdDIgPSB0ICogdCxcbiAgICAgICAgdDMgPSB0MiAqIHQ7XG4gICAgcmV0dXJuIDQgKiAodCA8IDAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAwLjc1KTtcbn07XG5cbi8qKlxuICogR2l2ZW4gZ2l2ZW4gKHgsIHkpLCAoeDEsIHkxKSBjb250cm9sIHBvaW50cyBmb3IgYSBiZXppZXIgY3VydmUsXG4gKiByZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGludGVycG9sYXRlcyBhbG9uZyB0aGF0IGN1cnZlLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMXggY29udHJvbCBwb2ludCAxIHggY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHAxeSBjb250cm9sIHBvaW50IDEgeSBjb29yZGluYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gcDJ4IGNvbnRyb2wgcG9pbnQgMiB4IGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMnkgY29udHJvbCBwb2ludCAyIHkgY29vcmRpbmF0ZVxuICogQHJldHVybnMge0Z1bmN0aW9ufSBpbnRlcnBvbGF0b3I6IHJlY2VpdmVzIG51bWJlciB2YWx1ZSwgcmV0dXJuc1xuICogbnVtYmVyIHZhbHVlLlxuICovXG5leHBvcnRzLmJlemllciA9IGZ1bmN0aW9uKHAxeCwgcDF5LCBwMngsIHAyeSkge1xuICAgIHZhciBiZXppZXIgPSBuZXcgVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiBiZXppZXIuc29sdmUodCk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogQSBkZWZhdWx0IGJlemllci1jdXJ2ZSBwb3dlcmVkIGVhc2luZyBmdW5jdGlvbiB3aXRoXG4gKiBjb250cm9sIHBvaW50cyAoMC4yNSwgMC4xKSBhbmQgKDAuMjUsIDEpXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IG91dHB1dFxuICovXG5leHBvcnRzLmVhc2UgPSBleHBvcnRzLmJlemllcigwLjI1LCAwLjEsIDAuMjUsIDEpO1xuXG4vKipcbiAqIEdpdmVuIGEgZm91ci1lbGVtZW50IGFycmF5IG9mIG51bWJlcnMgdGhhdCByZXByZXNlbnRzIGEgY29sb3IgaW5cbiAqIFJHQkEsIHJldHVybiBhIHZlcnNpb24gZm9yIHdoaWNoIHRoZSBSR0IgY29tcG9uZW50cyBhcmUgbXVsdGlwbGllZFxuICogYnkgdGhlIEEgKGFscGhhKSBjb21wb25lbnRcbiAqXG4gKiBAcGFyYW0ge051bWJlcjxBcnJheT59IGMgY29sb3IgYXJyYXlcbiAqIEByZXR1cm5zIHtOdW1iZXI8QXJyYXk+fSBwcmVtdWx0aXBsaWVkIGNvbG9yIGFycmF5XG4gKi9cbmV4cG9ydHMucHJlbXVsdGlwbHkgPSBmdW5jdGlvbiAoYykge1xuICAgIGNbMF0gKj0gY1szXTtcbiAgICBjWzFdICo9IGNbM107XG4gICAgY1syXSAqPSBjWzNdO1xuICAgIHJldHVybiBjO1xufTtcblxuLyoqXG4gKiBjb25zdHJhaW4gbiB0byB0aGUgZ2l2ZW4gcmFuZ2UgdmlhIG1pbiArIG1heFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuIHZhbHVlXG4gKiBAcGFyYW0ge051bWJlcn0gbWluIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4IHRoZSBtYXhpbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcmV0dXJucyB7TnVtYmVyfSB0aGUgY2xhbXBlZCB2YWx1ZVxuICovXG5leHBvcnRzLmNsYW1wID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCBuKSk7XG59O1xuXG4vKlxuICogY29uc3RyYWluIG4gdG8gdGhlIGdpdmVuIHJhbmdlIHZpYSBtb2R1bGFyIGFyaXRobWV0aWNcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcGFyYW0ge051bWJlcn0gbWluXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBjb25zdHJhaW5lZCBudW1iZXJcbiAqL1xuZXhwb3J0cy53cmFwID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgcmV0dXJuIG4gPT09IG1heCA/IG4gOiAoKG4gLSBtaW4pICUgZCArIGQpICUgZCArIG1pbjtcbn07XG5cbi8qXG4gKiByZXR1cm4gdGhlIGZpcnN0IG5vbi1udWxsIGFuZCBub24tdW5kZWZpbmVkIGFyZ3VtZW50IHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7Kn0gYXJndW1lbnRcbiAqL1xuZXhwb3J0cy5jb2FsZXNjZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGlmIChhcmcgIT09IG51bGwgJiYgYXJnICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gYXJnO1xuICAgIH1cbn07XG5cbi8qXG4gKiBDYWxsIGFuIGFzeW5jaHJvbm91cyBmdW5jdGlvbiBvbiBhbiBhcnJheSBvZiBhcmd1bWVudHMsXG4gKiBjYWxsaW5nIGBjYWxsYmFja2Agb25jZSBhbGwgY2FsbHMgY29tcGxldGUuXG4gKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyYXkgaW5wdXQgdG8gZWFjaCBjYWxsIG9mIHRoZSBhc3luYyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIGFuIGFzeW5jIGZ1bmN0aW9uIHdpdGggc2lnbmF0dXJlIChkYXRhLCBjYWxsYmFjaylcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgY2FsbGJhY2sgcnVuIGFmdGVyIGFsbCBhc3luYyB3b3JrIGlzIGRvbmUuXG4gKiBjYWxsZWQgd2l0aCBubyBhcmd1bWVudHNcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydHMuYXN5bmNFYWNoID0gZnVuY3Rpb24gKGFycmF5LCBmbiwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVtYWluaW5nID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChyZW1haW5pbmcgPT09IDApIHJldHVybiBjYWxsYmFjaygpO1xuICAgIGZ1bmN0aW9uIGNoZWNrKCkgeyBpZiAoLS1yZW1haW5pbmcgPT09IDApIGNhbGxiYWNrKCk7IH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBmbihhcnJheVtpXSwgY2hlY2spO1xufTtcblxuLypcbiAqIENvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUga2V5cyBpbiBvbmUgb2JqZWN0IGFuZCB0aGUga2V5c1xuICogaW4gYW5vdGhlciBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0ga2V5cyBkaWZmZXJlbmNlXG4gKi9cbmV4cG9ydHMua2V5c0RpZmZlcmVuY2UgPSBmdW5jdGlvbiAob2JqLCBvdGhlcikge1xuICAgIHZhciBkaWZmZXJlbmNlID0gW107XG4gICAgZm9yICh2YXIgaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKCEoaSBpbiBvdGhlcikpIHtcbiAgICAgICAgICAgIGRpZmZlcmVuY2UucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGlmZmVyZW5jZTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYSBkZXN0aW5hdGlvbiBvYmplY3QgYW5kIG9wdGlvbmFsbHkgbWFueSBzb3VyY2Ugb2JqZWN0cyxcbiAqIGNvcHkgYWxsIHByb3BlcnRpZXMgZnJvbSB0aGUgc291cmNlIG9iamVjdHMgaW50byB0aGUgZGVzdGluYXRpb24uXG4gKiBUaGUgbGFzdCBzb3VyY2Ugb2JqZWN0IGdpdmVuIG92ZXJyaWRlcyBwcm9wZXJ0aWVzIGZyb20gcHJldmlvdXNcbiAqIHNvdXJjZSBvYmplY3RzLlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3QgZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBzb3VyY2VzIGZyb20gd2hpY2ggcHJvcGVydGllcyBhcmUgcHVsbGVkXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBkZXN0XG4gKi9cbmV4cG9ydHMuZXh0ZW5kID0gZnVuY3Rpb24gKGRlc3QpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3JjID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrIGluIHNyYykge1xuICAgICAgICAgICAgZGVzdFtrXSA9IHNyY1trXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn07XG5cbi8qKlxuICogRXh0ZW5kIGEgZGVzdGluYXRpb24gb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb2YgdGhlIHNyYyBvYmplY3QsXG4gKiB1c2luZyBkZWZpbmVQcm9wZXJ0eSBpbnN0ZWFkIG9mIHNpbXBsZSBhc3NpZ25tZW50LlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBzcmNcbiAqIEByZXR1cm5zIHtPYmplY3R9IGRlc3RcbiAqL1xuZXhwb3J0cy5leHRlbmRBbGwgPSBmdW5jdGlvbiAoZGVzdCwgc3JjKSB7XG4gICAgZm9yICh2YXIgaSBpbiBzcmMpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIGksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc3JjLCBpKSk7XG4gICAgfVxuICAgIHJldHVybiBkZXN0O1xufTtcblxuLyoqXG4gKiBFeHRlbmQgYSBwYXJlbnQncyBwcm90b3R5cGUgd2l0aCBhbGwgcHJvcGVydGllcyBpbiBhIHByb3BlcnRpZXNcbiAqIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyZW50XG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAqIEByZXR1cm5zIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuaW5oZXJpdCA9IGZ1bmN0aW9uIChwYXJlbnQsIHByb3BzKSB7XG4gICAgdmFyIHBhcmVudFByb3RvID0gdHlwZW9mIHBhcmVudCA9PT0gJ2Z1bmN0aW9uJyA/IHBhcmVudC5wcm90b3R5cGUgOiBwYXJlbnQsXG4gICAgICAgIHByb3RvID0gT2JqZWN0LmNyZWF0ZShwYXJlbnRQcm90byk7XG4gICAgZXhwb3J0cy5leHRlbmRBbGwocHJvdG8sIHByb3BzKTtcbiAgICByZXR1cm4gcHJvdG87XG59O1xuXG4vKipcbiAqIEdpdmVuIGFuIG9iamVjdCBhbmQgYSBudW1iZXIgb2YgcHJvcGVydGllcyBhcyBzdHJpbmdzLCByZXR1cm4gdmVyc2lvblxuICogb2YgdGhhdCBvYmplY3Qgd2l0aCBvbmx5IHRob3NlIHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNyYyB0aGUgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IHByb3BlcnRpZXMgYW4gYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgY2hvc2VuXG4gKiB0byBhcHBlYXIgb24gdGhlIHJlc3VsdGluZyBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3Qgd2l0aCBsaW1pdGVkIHByb3BlcnRpZXMuXG4gKiBAZXhhbXBsZVxuICogdmFyIGZvbyA9IHsgbmFtZTogJ0NoYXJsaWUnLCBhZ2U6IDEwIH07XG4gKiB2YXIganVzdE5hbWUgPSBwaWNrKGZvbywgWyduYW1lJ10pO1xuICogLy8ganVzdE5hbWUgPSB7IG5hbWU6ICdDaGFybGllJyB9XG4gKi9cbmV4cG9ydHMucGljayA9IGZ1bmN0aW9uIChzcmMsIHByb3BlcnRpZXMpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgaWYgKGsgaW4gc3JjKSB7XG4gICAgICAgICAgICByZXN1bHRba10gPSBzcmNba107XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbnZhciBpZCA9IDE7XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pcXVlIG51bWVyaWMgaWQsIHN0YXJ0aW5nIGF0IDEgYW5kIGluY3JlbWVudGluZyB3aXRoXG4gKiBlYWNoIGNhbGwuXG4gKlxuICogQHJldHVybnMge051bWJlcn0gdW5pcXVlIG51bWVyaWMgaWQuXG4gKi9cbmV4cG9ydHMudW5pcXVlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGlkKys7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIHZlcnNpb24gb2YgYGZuYCB0aGF0IG9ubHkgZmlyZXMgb25jZSBldmVyeSBgdGltZWAgbWlsbHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gdGhlIGZ1bmN0aW9uIHRvIGJlIHRocm90dGxlZFxuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWUgbWlsbHNlY29uZHMgcmVxdWlyZWQgYmV0d2VlbiBmdW5jdGlvbiBjYWxsc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSB2YWx1ZSBvZiBgdGhpc2Agd2l0aCB3aGljaCB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IGRlYm91bmNlZCBmdW5jdGlvblxuICovXG5leHBvcnRzLnRocm90dGxlID0gZnVuY3Rpb24gKGZuLCB0aW1lLCBjb250ZXh0KSB7XG4gICAgdmFyIGxvY2ssIGFyZ3MsIHdyYXBwZXJGbiwgbGF0ZXI7XG5cbiAgICBsYXRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcbiAgICAgICAgbG9jayA9IGZhbHNlO1xuICAgICAgICBpZiAoYXJncykge1xuICAgICAgICAgICAgd3JhcHBlckZuLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgYXJncyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdyYXBwZXJGbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGxvY2spIHtcbiAgICAgICAgICAgIC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxuICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY2FsbCBhbmQgbG9jayB1bnRpbCBsYXRlclxuICAgICAgICAgICAgZm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xuICAgICAgICAgICAgbG9jayA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHdyYXBwZXJGbjtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgdmVyc2lvbiBvZiBgZm5gIHRoYXQgaXMgb25seSBjYWxsZWQgYHRpbWVgIG1pbGxpc2Vjb25kc1xuICogYWZ0ZXIgaXRzIGxhc3QgaW52b2NhdGlvblxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIHRoZSBmdW5jdGlvbiB0byBiZSBkZWJvdW5jZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lIG1pbGxzZWNvbmRzIGFmdGVyIHdoaWNoIHRoZSBmdW5jdGlvbiB3aWxsIGJlIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZGVib3VuY2VkIGZ1bmN0aW9uXG4gKi9cbmV4cG9ydHMuZGVib3VuY2UgPSBmdW5jdGlvbihmbiwgdGltZSkge1xuICAgIHZhciB0aW1lciwgYXJncztcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcblxuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgfSwgdGltZSk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYW4gYXJyYXkgb2YgbWVtYmVyIGZ1bmN0aW9uIG5hbWVzIGFzIHN0cmluZ3MsIHJlcGxhY2UgYWxsIG9mIHRoZW1cbiAqIHdpdGggYm91bmQgdmVyc2lvbnMgdGhhdCB3aWxsIGFsd2F5cyByZWZlciB0byBgY29udGV4dGAgYXMgYHRoaXNgLiBUaGlzXG4gKiBpcyB1c2VmdWwgZm9yIGNsYXNzZXMgd2hlcmUgb3RoZXJ3aXNlIGV2ZW50IGJpbmRpbmdzIHdvdWxkIHJlYXNzaWduXG4gKiBgdGhpc2AgdG8gdGhlIGV2ZW50ZWQgb2JqZWN0IG9yIHNvbWUgb3RoZXIgdmFsdWU6IHRoaXMgbGV0cyB5b3UgZW5zdXJlXG4gKiB0aGUgYHRoaXNgIHZhbHVlIGFsd2F5cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGZucyBsaXN0IG9mIG1lbWJlciBmdW5jdGlvbiBuYW1lc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSBjb250ZXh0IHZhbHVlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBjaGFuZ2VzIGZ1bmN0aW9ucyBpbi1wbGFjZVxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIE15Q2xhc3MoKSB7XG4gKiAgIGJpbmRBbGwoWydvbnRpbWVyJ10sIHRoaXMpO1xuICogICB0aGlzLm5hbWUgPSAnVG9tJztcbiAqIH1cbiAqIE15Q2xhc3MucHJvdG90eXBlLm9udGltZXIgPSBmdW5jdGlvbigpIHtcbiAqICAgYWxlcnQodGhpcy5uYW1lKTtcbiAqIH07XG4gKiB2YXIgbXlDbGFzcyA9IG5ldyBNeUNsYXNzKCk7XG4gKiBzZXRUaW1lb3V0KG15Q2xhc3Mub250aW1lciwgMTAwKTtcbiAqL1xuZXhwb3J0cy5iaW5kQWxsID0gZnVuY3Rpb24oZm5zLCBjb250ZXh0KSB7XG4gICAgZm5zLmZvckVhY2goZnVuY3Rpb24oZm4pIHtcbiAgICAgICAgY29udGV4dFtmbl0gPSBjb250ZXh0W2ZuXS5iaW5kKGNvbnRleHQpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlICdvcHRpb25zJyBwcm9wZXJ0eSBvbiBgb2JqYCB3aXRoIHByb3BlcnRpZXNcbiAqIGZyb20gdGhlIGBvcHRpb25zYCBhcmd1bWVudC4gUHJvcGVydGllcyBpbiB0aGUgYG9wdGlvbnNgXG4gKiBvYmplY3Qgd2lsbCBvdmVycmlkZSBleGlzdGluZyBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvYmplY3Qgb2Ygb3ZlcnJpZGUgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gZGVyaXZlZCBvcHRpb25zIG9iamVjdC5cbiAqL1xuZXhwb3J0cy5zZXRPcHRpb25zID0gZnVuY3Rpb24ob2JqLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSkge1xuICAgICAgICBvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gT2JqZWN0LmNyZWF0ZShvYmoub3B0aW9ucykgOiB7fTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XG4gICAgICAgIG9iai5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG9iai5vcHRpb25zO1xufTtcbiIsIi8vIChjKSBEZWFuIE1jTmFtZWUgPGRlYW5AZ21haWwuY29tPiwgMjAxMi5cbi8vXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZGVhbm0vY3NzLWNvbG9yLXBhcnNlci1qc1xuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4vLyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4vLyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtY29sb3IvXG52YXIga0NTU0NvbG9yVGFibGUgPSB7XG4gIFwidHJhbnNwYXJlbnRcIjogWzAsMCwwLDBdLCBcImFsaWNlYmx1ZVwiOiBbMjQwLDI0OCwyNTUsMV0sXG4gIFwiYW50aXF1ZXdoaXRlXCI6IFsyNTAsMjM1LDIxNSwxXSwgXCJhcXVhXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiYXF1YW1hcmluZVwiOiBbMTI3LDI1NSwyMTIsMV0sIFwiYXp1cmVcIjogWzI0MCwyNTUsMjU1LDFdLFxuICBcImJlaWdlXCI6IFsyNDUsMjQ1LDIyMCwxXSwgXCJiaXNxdWVcIjogWzI1NSwyMjgsMTk2LDFdLFxuICBcImJsYWNrXCI6IFswLDAsMCwxXSwgXCJibGFuY2hlZGFsbW9uZFwiOiBbMjU1LDIzNSwyMDUsMV0sXG4gIFwiYmx1ZVwiOiBbMCwwLDI1NSwxXSwgXCJibHVldmlvbGV0XCI6IFsxMzgsNDMsMjI2LDFdLFxuICBcImJyb3duXCI6IFsxNjUsNDIsNDIsMV0sIFwiYnVybHl3b29kXCI6IFsyMjIsMTg0LDEzNSwxXSxcbiAgXCJjYWRldGJsdWVcIjogWzk1LDE1OCwxNjAsMV0sIFwiY2hhcnRyZXVzZVwiOiBbMTI3LDI1NSwwLDFdLFxuICBcImNob2NvbGF0ZVwiOiBbMjEwLDEwNSwzMCwxXSwgXCJjb3JhbFwiOiBbMjU1LDEyNyw4MCwxXSxcbiAgXCJjb3JuZmxvd2VyYmx1ZVwiOiBbMTAwLDE0OSwyMzcsMV0sIFwiY29ybnNpbGtcIjogWzI1NSwyNDgsMjIwLDFdLFxuICBcImNyaW1zb25cIjogWzIyMCwyMCw2MCwxXSwgXCJjeWFuXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiZGFya2JsdWVcIjogWzAsMCwxMzksMV0sIFwiZGFya2N5YW5cIjogWzAsMTM5LDEzOSwxXSxcbiAgXCJkYXJrZ29sZGVucm9kXCI6IFsxODQsMTM0LDExLDFdLCBcImRhcmtncmF5XCI6IFsxNjksMTY5LDE2OSwxXSxcbiAgXCJkYXJrZ3JlZW5cIjogWzAsMTAwLDAsMV0sIFwiZGFya2dyZXlcIjogWzE2OSwxNjksMTY5LDFdLFxuICBcImRhcmtraGFraVwiOiBbMTg5LDE4MywxMDcsMV0sIFwiZGFya21hZ2VudGFcIjogWzEzOSwwLDEzOSwxXSxcbiAgXCJkYXJrb2xpdmVncmVlblwiOiBbODUsMTA3LDQ3LDFdLCBcImRhcmtvcmFuZ2VcIjogWzI1NSwxNDAsMCwxXSxcbiAgXCJkYXJrb3JjaGlkXCI6IFsxNTMsNTAsMjA0LDFdLCBcImRhcmtyZWRcIjogWzEzOSwwLDAsMV0sXG4gIFwiZGFya3NhbG1vblwiOiBbMjMzLDE1MCwxMjIsMV0sIFwiZGFya3NlYWdyZWVuXCI6IFsxNDMsMTg4LDE0MywxXSxcbiAgXCJkYXJrc2xhdGVibHVlXCI6IFs3Miw2MSwxMzksMV0sIFwiZGFya3NsYXRlZ3JheVwiOiBbNDcsNzksNzksMV0sXG4gIFwiZGFya3NsYXRlZ3JleVwiOiBbNDcsNzksNzksMV0sIFwiZGFya3R1cnF1b2lzZVwiOiBbMCwyMDYsMjA5LDFdLFxuICBcImRhcmt2aW9sZXRcIjogWzE0OCwwLDIxMSwxXSwgXCJkZWVwcGlua1wiOiBbMjU1LDIwLDE0NywxXSxcbiAgXCJkZWVwc2t5Ymx1ZVwiOiBbMCwxOTEsMjU1LDFdLCBcImRpbWdyYXlcIjogWzEwNSwxMDUsMTA1LDFdLFxuICBcImRpbWdyZXlcIjogWzEwNSwxMDUsMTA1LDFdLCBcImRvZGdlcmJsdWVcIjogWzMwLDE0NCwyNTUsMV0sXG4gIFwiZmlyZWJyaWNrXCI6IFsxNzgsMzQsMzQsMV0sIFwiZmxvcmFsd2hpdGVcIjogWzI1NSwyNTAsMjQwLDFdLFxuICBcImZvcmVzdGdyZWVuXCI6IFszNCwxMzksMzQsMV0sIFwiZnVjaHNpYVwiOiBbMjU1LDAsMjU1LDFdLFxuICBcImdhaW5zYm9yb1wiOiBbMjIwLDIyMCwyMjAsMV0sIFwiZ2hvc3R3aGl0ZVwiOiBbMjQ4LDI0OCwyNTUsMV0sXG4gIFwiZ29sZFwiOiBbMjU1LDIxNSwwLDFdLCBcImdvbGRlbnJvZFwiOiBbMjE4LDE2NSwzMiwxXSxcbiAgXCJncmF5XCI6IFsxMjgsMTI4LDEyOCwxXSwgXCJncmVlblwiOiBbMCwxMjgsMCwxXSxcbiAgXCJncmVlbnllbGxvd1wiOiBbMTczLDI1NSw0NywxXSwgXCJncmV5XCI6IFsxMjgsMTI4LDEyOCwxXSxcbiAgXCJob25leWRld1wiOiBbMjQwLDI1NSwyNDAsMV0sIFwiaG90cGlua1wiOiBbMjU1LDEwNSwxODAsMV0sXG4gIFwiaW5kaWFucmVkXCI6IFsyMDUsOTIsOTIsMV0sIFwiaW5kaWdvXCI6IFs3NSwwLDEzMCwxXSxcbiAgXCJpdm9yeVwiOiBbMjU1LDI1NSwyNDAsMV0sIFwia2hha2lcIjogWzI0MCwyMzAsMTQwLDFdLFxuICBcImxhdmVuZGVyXCI6IFsyMzAsMjMwLDI1MCwxXSwgXCJsYXZlbmRlcmJsdXNoXCI6IFsyNTUsMjQwLDI0NSwxXSxcbiAgXCJsYXduZ3JlZW5cIjogWzEyNCwyNTIsMCwxXSwgXCJsZW1vbmNoaWZmb25cIjogWzI1NSwyNTAsMjA1LDFdLFxuICBcImxpZ2h0Ymx1ZVwiOiBbMTczLDIxNiwyMzAsMV0sIFwibGlnaHRjb3JhbFwiOiBbMjQwLDEyOCwxMjgsMV0sXG4gIFwibGlnaHRjeWFuXCI6IFsyMjQsMjU1LDI1NSwxXSwgXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiOiBbMjUwLDI1MCwyMTAsMV0sXG4gIFwibGlnaHRncmF5XCI6IFsyMTEsMjExLDIxMSwxXSwgXCJsaWdodGdyZWVuXCI6IFsxNDQsMjM4LDE0NCwxXSxcbiAgXCJsaWdodGdyZXlcIjogWzIxMSwyMTEsMjExLDFdLCBcImxpZ2h0cGlua1wiOiBbMjU1LDE4MiwxOTMsMV0sXG4gIFwibGlnaHRzYWxtb25cIjogWzI1NSwxNjAsMTIyLDFdLCBcImxpZ2h0c2VhZ3JlZW5cIjogWzMyLDE3OCwxNzAsMV0sXG4gIFwibGlnaHRza3libHVlXCI6IFsxMzUsMjA2LDI1MCwxXSwgXCJsaWdodHNsYXRlZ3JheVwiOiBbMTE5LDEzNiwxNTMsMV0sXG4gIFwibGlnaHRzbGF0ZWdyZXlcIjogWzExOSwxMzYsMTUzLDFdLCBcImxpZ2h0c3RlZWxibHVlXCI6IFsxNzYsMTk2LDIyMiwxXSxcbiAgXCJsaWdodHllbGxvd1wiOiBbMjU1LDI1NSwyMjQsMV0sIFwibGltZVwiOiBbMCwyNTUsMCwxXSxcbiAgXCJsaW1lZ3JlZW5cIjogWzUwLDIwNSw1MCwxXSwgXCJsaW5lblwiOiBbMjUwLDI0MCwyMzAsMV0sXG4gIFwibWFnZW50YVwiOiBbMjU1LDAsMjU1LDFdLCBcIm1hcm9vblwiOiBbMTI4LDAsMCwxXSxcbiAgXCJtZWRpdW1hcXVhbWFyaW5lXCI6IFsxMDIsMjA1LDE3MCwxXSwgXCJtZWRpdW1ibHVlXCI6IFswLDAsMjA1LDFdLFxuICBcIm1lZGl1bW9yY2hpZFwiOiBbMTg2LDg1LDIxMSwxXSwgXCJtZWRpdW1wdXJwbGVcIjogWzE0NywxMTIsMjE5LDFdLFxuICBcIm1lZGl1bXNlYWdyZWVuXCI6IFs2MCwxNzksMTEzLDFdLCBcIm1lZGl1bXNsYXRlYmx1ZVwiOiBbMTIzLDEwNCwyMzgsMV0sXG4gIFwibWVkaXVtc3ByaW5nZ3JlZW5cIjogWzAsMjUwLDE1NCwxXSwgXCJtZWRpdW10dXJxdW9pc2VcIjogWzcyLDIwOSwyMDQsMV0sXG4gIFwibWVkaXVtdmlvbGV0cmVkXCI6IFsxOTksMjEsMTMzLDFdLCBcIm1pZG5pZ2h0Ymx1ZVwiOiBbMjUsMjUsMTEyLDFdLFxuICBcIm1pbnRjcmVhbVwiOiBbMjQ1LDI1NSwyNTAsMV0sIFwibWlzdHlyb3NlXCI6IFsyNTUsMjI4LDIyNSwxXSxcbiAgXCJtb2NjYXNpblwiOiBbMjU1LDIyOCwxODEsMV0sIFwibmF2YWpvd2hpdGVcIjogWzI1NSwyMjIsMTczLDFdLFxuICBcIm5hdnlcIjogWzAsMCwxMjgsMV0sIFwib2xkbGFjZVwiOiBbMjUzLDI0NSwyMzAsMV0sXG4gIFwib2xpdmVcIjogWzEyOCwxMjgsMCwxXSwgXCJvbGl2ZWRyYWJcIjogWzEwNywxNDIsMzUsMV0sXG4gIFwib3JhbmdlXCI6IFsyNTUsMTY1LDAsMV0sIFwib3JhbmdlcmVkXCI6IFsyNTUsNjksMCwxXSxcbiAgXCJvcmNoaWRcIjogWzIxOCwxMTIsMjE0LDFdLCBcInBhbGVnb2xkZW5yb2RcIjogWzIzOCwyMzIsMTcwLDFdLFxuICBcInBhbGVncmVlblwiOiBbMTUyLDI1MSwxNTIsMV0sIFwicGFsZXR1cnF1b2lzZVwiOiBbMTc1LDIzOCwyMzgsMV0sXG4gIFwicGFsZXZpb2xldHJlZFwiOiBbMjE5LDExMiwxNDcsMV0sIFwicGFwYXlhd2hpcFwiOiBbMjU1LDIzOSwyMTMsMV0sXG4gIFwicGVhY2hwdWZmXCI6IFsyNTUsMjE4LDE4NSwxXSwgXCJwZXJ1XCI6IFsyMDUsMTMzLDYzLDFdLFxuICBcInBpbmtcIjogWzI1NSwxOTIsMjAzLDFdLCBcInBsdW1cIjogWzIyMSwxNjAsMjIxLDFdLFxuICBcInBvd2RlcmJsdWVcIjogWzE3NiwyMjQsMjMwLDFdLCBcInB1cnBsZVwiOiBbMTI4LDAsMTI4LDFdLFxuICBcInJlZFwiOiBbMjU1LDAsMCwxXSwgXCJyb3N5YnJvd25cIjogWzE4OCwxNDMsMTQzLDFdLFxuICBcInJveWFsYmx1ZVwiOiBbNjUsMTA1LDIyNSwxXSwgXCJzYWRkbGVicm93blwiOiBbMTM5LDY5LDE5LDFdLFxuICBcInNhbG1vblwiOiBbMjUwLDEyOCwxMTQsMV0sIFwic2FuZHlicm93blwiOiBbMjQ0LDE2NCw5NiwxXSxcbiAgXCJzZWFncmVlblwiOiBbNDYsMTM5LDg3LDFdLCBcInNlYXNoZWxsXCI6IFsyNTUsMjQ1LDIzOCwxXSxcbiAgXCJzaWVubmFcIjogWzE2MCw4Miw0NSwxXSwgXCJzaWx2ZXJcIjogWzE5MiwxOTIsMTkyLDFdLFxuICBcInNreWJsdWVcIjogWzEzNSwyMDYsMjM1LDFdLCBcInNsYXRlYmx1ZVwiOiBbMTA2LDkwLDIwNSwxXSxcbiAgXCJzbGF0ZWdyYXlcIjogWzExMiwxMjgsMTQ0LDFdLCBcInNsYXRlZ3JleVwiOiBbMTEyLDEyOCwxNDQsMV0sXG4gIFwic25vd1wiOiBbMjU1LDI1MCwyNTAsMV0sIFwic3ByaW5nZ3JlZW5cIjogWzAsMjU1LDEyNywxXSxcbiAgXCJzdGVlbGJsdWVcIjogWzcwLDEzMCwxODAsMV0sIFwidGFuXCI6IFsyMTAsMTgwLDE0MCwxXSxcbiAgXCJ0ZWFsXCI6IFswLDEyOCwxMjgsMV0sIFwidGhpc3RsZVwiOiBbMjE2LDE5MSwyMTYsMV0sXG4gIFwidG9tYXRvXCI6IFsyNTUsOTksNzEsMV0sIFwidHVycXVvaXNlXCI6IFs2NCwyMjQsMjA4LDFdLFxuICBcInZpb2xldFwiOiBbMjM4LDEzMCwyMzgsMV0sIFwid2hlYXRcIjogWzI0NSwyMjIsMTc5LDFdLFxuICBcIndoaXRlXCI6IFsyNTUsMjU1LDI1NSwxXSwgXCJ3aGl0ZXNtb2tlXCI6IFsyNDUsMjQ1LDI0NSwxXSxcbiAgXCJ5ZWxsb3dcIjogWzI1NSwyNTUsMCwxXSwgXCJ5ZWxsb3dncmVlblwiOiBbMTU0LDIwNSw1MCwxXX1cblxuZnVuY3Rpb24gY2xhbXBfY3NzX2J5dGUoaSkgeyAgLy8gQ2xhbXAgdG8gaW50ZWdlciAwIC4uIDI1NS5cbiAgaSA9IE1hdGgucm91bmQoaSk7ICAvLyBTZWVtcyB0byBiZSB3aGF0IENocm9tZSBkb2VzICh2cyB0cnVuY2F0aW9uKS5cbiAgcmV0dXJuIGkgPCAwID8gMCA6IGkgPiAyNTUgPyAyNTUgOiBpO1xufVxuXG5mdW5jdGlvbiBjbGFtcF9jc3NfZmxvYXQoZikgeyAgLy8gQ2xhbXAgdG8gZmxvYXQgMC4wIC4uIDEuMC5cbiAgcmV0dXJuIGYgPCAwID8gMCA6IGYgPiAxID8gMSA6IGY7XG59XG5cbmZ1bmN0aW9uIHBhcnNlX2Nzc19pbnQoc3RyKSB7ICAvLyBpbnQgb3IgcGVyY2VudGFnZS5cbiAgaWYgKHN0cltzdHIubGVuZ3RoIC0gMV0gPT09ICclJylcbiAgICByZXR1cm4gY2xhbXBfY3NzX2J5dGUocGFyc2VGbG9hdChzdHIpIC8gMTAwICogMjU1KTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19ieXRlKHBhcnNlSW50KHN0cikpO1xufVxuXG5mdW5jdGlvbiBwYXJzZV9jc3NfZmxvYXQoc3RyKSB7ICAvLyBmbG9hdCBvciBwZXJjZW50YWdlLlxuICBpZiAoc3RyW3N0ci5sZW5ndGggLSAxXSA9PT0gJyUnKVxuICAgIHJldHVybiBjbGFtcF9jc3NfZmxvYXQocGFyc2VGbG9hdChzdHIpIC8gMTAwKTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19mbG9hdChwYXJzZUZsb2F0KHN0cikpO1xufVxuXG5mdW5jdGlvbiBjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgpIHtcbiAgaWYgKGggPCAwKSBoICs9IDE7XG4gIGVsc2UgaWYgKGggPiAxKSBoIC09IDE7XG5cbiAgaWYgKGggKiA2IDwgMSkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogaCAqIDY7XG4gIGlmIChoICogMiA8IDEpIHJldHVybiBtMjtcbiAgaWYgKGggKiAzIDwgMikgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDIvMyAtIGgpICogNjtcbiAgcmV0dXJuIG0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNTU0NvbG9yKGNzc19zdHIpIHtcbiAgLy8gUmVtb3ZlIGFsbCB3aGl0ZXNwYWNlLCBub3QgY29tcGxpYW50LCBidXQgc2hvdWxkIGp1c3QgYmUgbW9yZSBhY2NlcHRpbmcuXG4gIHZhciBzdHIgPSBjc3Nfc3RyLnJlcGxhY2UoLyAvZywgJycpLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gQ29sb3Iga2V5d29yZHMgKGFuZCB0cmFuc3BhcmVudCkgbG9va3VwLlxuICBpZiAoc3RyIGluIGtDU1NDb2xvclRhYmxlKSByZXR1cm4ga0NTU0NvbG9yVGFibGVbc3RyXS5zbGljZSgpOyAgLy8gZHVwLlxuXG4gIC8vICNhYmMgYW5kICNhYmMxMjMgc3ludGF4LlxuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gNCkge1xuICAgICAgdmFyIGl2ID0gcGFyc2VJbnQoc3RyLnN1YnN0cigxKSwgMTYpOyAgLy8gVE9ETyhkZWFubSk6IFN0cmljdGVyIHBhcnNpbmcuXG4gICAgICBpZiAoIShpdiA+PSAwICYmIGl2IDw9IDB4ZmZmKSkgcmV0dXJuIG51bGw7ICAvLyBDb3ZlcnMgTmFOLlxuICAgICAgcmV0dXJuIFsoKGl2ICYgMHhmMDApID4+IDQpIHwgKChpdiAmIDB4ZjAwKSA+PiA4KSxcbiAgICAgICAgICAgICAgKGl2ICYgMHhmMCkgfCAoKGl2ICYgMHhmMCkgPj4gNCksXG4gICAgICAgICAgICAgIChpdiAmIDB4ZikgfCAoKGl2ICYgMHhmKSA8PCA0KSxcbiAgICAgICAgICAgICAgMV07XG4gICAgfSBlbHNlIGlmIChzdHIubGVuZ3RoID09PSA3KSB7XG4gICAgICB2YXIgaXYgPSBwYXJzZUludChzdHIuc3Vic3RyKDEpLCAxNik7ICAvLyBUT0RPKGRlYW5tKTogU3RyaWN0ZXIgcGFyc2luZy5cbiAgICAgIGlmICghKGl2ID49IDAgJiYgaXYgPD0gMHhmZmZmZmYpKSByZXR1cm4gbnVsbDsgIC8vIENvdmVycyBOYU4uXG4gICAgICByZXR1cm4gWyhpdiAmIDB4ZmYwMDAwKSA+PiAxNixcbiAgICAgICAgICAgICAgKGl2ICYgMHhmZjAwKSA+PiA4LFxuICAgICAgICAgICAgICBpdiAmIDB4ZmYsXG4gICAgICAgICAgICAgIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIG9wID0gc3RyLmluZGV4T2YoJygnKSwgZXAgPSBzdHIuaW5kZXhPZignKScpO1xuICBpZiAob3AgIT09IC0xICYmIGVwICsgMSA9PT0gc3RyLmxlbmd0aCkge1xuICAgIHZhciBmbmFtZSA9IHN0ci5zdWJzdHIoMCwgb3ApO1xuICAgIHZhciBwYXJhbXMgPSBzdHIuc3Vic3RyKG9wKzEsIGVwLShvcCsxKSkuc3BsaXQoJywnKTtcbiAgICB2YXIgYWxwaGEgPSAxOyAgLy8gVG8gYWxsb3cgY2FzZSBmYWxsdGhyb3VnaC5cbiAgICBzd2l0Y2ggKGZuYW1lKSB7XG4gICAgICBjYXNlICdyZ2JhJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDQpIHJldHVybiBudWxsO1xuICAgICAgICBhbHBoYSA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXMucG9wKCkpO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2guXG4gICAgICBjYXNlICdyZ2InOlxuICAgICAgICBpZiAocGFyYW1zLmxlbmd0aCAhPT0gMykgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBbcGFyc2VfY3NzX2ludChwYXJhbXNbMF0pLFxuICAgICAgICAgICAgICAgIHBhcnNlX2Nzc19pbnQocGFyYW1zWzFdKSxcbiAgICAgICAgICAgICAgICBwYXJzZV9jc3NfaW50KHBhcmFtc1syXSksXG4gICAgICAgICAgICAgICAgYWxwaGFdO1xuICAgICAgY2FzZSAnaHNsYSc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSA0KSByZXR1cm4gbnVsbDtcbiAgICAgICAgYWxwaGEgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zLnBvcCgpKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoLlxuICAgICAgY2FzZSAnaHNsJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgaCA9ICgoKHBhcnNlRmxvYXQocGFyYW1zWzBdKSAlIDM2MCkgKyAzNjApICUgMzYwKSAvIDM2MDsgIC8vIDAgLi4gMVxuICAgICAgICAvLyBOT1RFKGRlYW5tKTogQWNjb3JkaW5nIHRvIHRoZSBDU1Mgc3BlYyBzL2wgc2hvdWxkIG9ubHkgYmVcbiAgICAgICAgLy8gcGVyY2VudGFnZXMsIGJ1dCB3ZSBkb24ndCBib3RoZXIgYW5kIGxldCBmbG9hdCBvciBwZXJjZW50YWdlLlxuICAgICAgICB2YXIgcyA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMV0pO1xuICAgICAgICB2YXIgbCA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMl0pO1xuICAgICAgICB2YXIgbTIgPSBsIDw9IDAuNSA/IGwgKiAocyArIDEpIDogbCArIHMgLSBsICogcztcbiAgICAgICAgdmFyIG0xID0gbCAqIDIgLSBtMjtcbiAgICAgICAgcmV0dXJuIFtjbGFtcF9jc3NfYnl0ZShjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgrMS8zKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoLTEvMykgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGFscGhhXTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG50cnkgeyBleHBvcnRzLnBhcnNlQ1NTQ29sb3IgPSBwYXJzZUNTU0NvbG9yIH0gY2F0Y2goZSkgeyB9XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZVR5cGVzID0gWydVbmtub3duJywgJ1BvaW50JywgJ0xpbmVTdHJpbmcnLCAnUG9seWdvbiddO1xuXG5mdW5jdGlvbiBpbmZpeChvcGVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiAndCcgKyBvcGVyYXRvciArIFZlY3RvclRpbGVGZWF0dXJlVHlwZXMuaW5kZXhPZih2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXScgKyBvcGVyYXRvciArIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdEluZml4KG9wZXJhdG9yKSB7XG4gICAgdmFyIG5vbnN0cmljdEluZml4ID0gaW5maXgob3BlcmF0b3IpO1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiBub25zdHJpY3RJbmZpeChfLCBrZXksIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAndHlwZW9mKHBbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSkgPT09IHR5cGVvZignICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpICsgJykgJiYgJyArXG4gICAgICAgICAgICAgICAgbm9uc3RyaWN0SW5maXgoXywga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgb3BlcmF0b3JzID0ge1xuICAgICc9PSc6IGluZml4KCc9PT0nKSxcbiAgICAnIT0nOiBpbmZpeCgnIT09JyksXG4gICAgJz4nOiBzdHJpY3RJbmZpeCgnPicpLFxuICAgICc8Jzogc3RyaWN0SW5maXgoJzwnKSxcbiAgICAnPD0nOiBzdHJpY3RJbmZpeCgnPD0nKSxcbiAgICAnPj0nOiBzdHJpY3RJbmZpeCgnPj0nKSxcbiAgICAnaW4nOiBmdW5jdGlvbihfLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMikubWFwKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gJygnICsgb3BlcmF0b3JzWyc9PSddKF8sIGtleSwgdmFsdWUpICsgJyknO1xuICAgICAgICB9KS5qb2luKCd8fCcpIHx8ICdmYWxzZSc7XG4gICAgfSxcbiAgICAnIWluJzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAnISgnICsgb3BlcmF0b3JzLmluLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKyAnKSc7XG4gICAgfSxcbiAgICAnYW55JzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLm1hcChmdW5jdGlvbihmaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBjb21waWxlKGZpbHRlcikgKyAnKSc7XG4gICAgICAgIH0pLmpvaW4oJ3x8JykgfHwgJ2ZhbHNlJztcbiAgICB9LFxuICAgICdhbGwnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkubWFwKGZ1bmN0aW9uKGZpbHRlcikge1xuICAgICAgICAgICAgcmV0dXJuICcoJyArIGNvbXBpbGUoZmlsdGVyKSArICcpJztcbiAgICAgICAgfSkuam9pbignJiYnKSB8fCAndHJ1ZSc7XG4gICAgfSxcbiAgICAnbm9uZSc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gJyEoJyArIG9wZXJhdG9ycy5hbnkuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICcpJztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb21waWxlKGZpbHRlcikge1xuICAgIHJldHVybiBvcGVyYXRvcnNbZmlsdGVyWzBdXS5hcHBseShmaWx0ZXIsIGZpbHRlcik7XG59XG5cbmZ1bmN0aW9uIHRydXRoKCkge1xuICAgIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgZmlsdGVyIGV4cHJlc3NlZCBhcyBuZXN0ZWQgYXJyYXlzLCByZXR1cm4gYSBuZXcgZnVuY3Rpb25cbiAqIHRoYXQgZXZhbHVhdGVzIHdoZXRoZXIgYSBnaXZlbiBmZWF0dXJlICh3aXRoIGEgLnByb3BlcnRpZXMgb3IgLnRhZ3MgcHJvcGVydHkpXG4gKiBwYXNzZXMgaXRzIHRlc3QuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gZmlsdGVyIG1hcGJveCBnbCBmaWx0ZXJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZmlsdGVyLWV2YWx1YXRpbmcgZnVuY3Rpb25cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgaWYgKCFmaWx0ZXIpIHJldHVybiB0cnV0aDtcbiAgICB2YXIgZmlsdGVyU3RyID0gJ3ZhciBwID0gZi5wcm9wZXJ0aWVzIHx8IGYudGFncyB8fCB7fSwgdCA9IGYudHlwZTsgcmV0dXJuICcgKyBjb21waWxlKGZpbHRlcikgKyAnOyc7XG4gICAgLy8ganNoaW50IGV2aWw6IHRydWVcbiAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCdmJywgZmlsdGVyU3RyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY2xpcDtcblxuLyogY2xpcCBmZWF0dXJlcyBiZXR3ZWVuIHR3byBheGlzLXBhcmFsbGVsIGxpbmVzOlxuICogICAgIHwgICAgICAgIHxcbiAqICBfX198X19fICAgICB8ICAgICAvXG4gKiAvICAgfCAgIFxcX19fX3xfX19fL1xuICogICAgIHwgICAgICAgIHxcbiAqL1xuXG5mdW5jdGlvbiBjbGlwKGZlYXR1cmVzLCBzY2FsZSwgazEsIGsyLCBheGlzLCBpbnRlcnNlY3QpIHtcblxuICAgIGsxIC89IHNjYWxlO1xuICAgIGsyIC89IHNjYWxlO1xuXG4gICAgdmFyIGNsaXBwZWQgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldLFxuICAgICAgICAgICAgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICAgICAgdHlwZSA9IGZlYXR1cmUudHlwZSxcbiAgICAgICAgICAgIG1pbiwgbWF4O1xuXG4gICAgICAgIGlmIChmZWF0dXJlLm1pbikge1xuICAgICAgICAgICAgbWluID0gZmVhdHVyZS5taW5bYXhpc107XG4gICAgICAgICAgICBtYXggPSBmZWF0dXJlLm1heFtheGlzXTtcblxuICAgICAgICAgICAgaWYgKG1pbiA+PSBrMSAmJiBtYXggPD0gazIpIHsgLy8gdHJpdmlhbCBhY2NlcHRcbiAgICAgICAgICAgICAgICBjbGlwcGVkLnB1c2goZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IGsyIHx8IG1heCA8IGsxKSBjb250aW51ZTsgLy8gdHJpdmlhbCByZWplY3RcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzbGljZXMgPSB0eXBlID09PSAxID9cbiAgICAgICAgICAgICAgICBjbGlwUG9pbnRzKGdlb21ldHJ5LCBrMSwgazIsIGF4aXMpIDpcbiAgICAgICAgICAgICAgICBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCB0eXBlID09PSAzKTtcblxuICAgICAgICBpZiAoc2xpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gaWYgYSBmZWF0dXJlIGdvdCBjbGlwcGVkLCBpdCB3aWxsIGxpa2VseSBnZXQgY2xpcHBlZCBvbiB0aGUgbmV4dCB6b29tIGxldmVsIGFzIHdlbGwsXG4gICAgICAgICAgICAvLyBzbyB0aGVyZSdzIG5vIG5lZWQgdG8gcmVjYWxjdWxhdGUgYmJveGVzXG4gICAgICAgICAgICBjbGlwcGVkLnB1c2goe1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5OiBzbGljZXMsXG4gICAgICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgICAgICB0YWdzOiBmZWF0dXJlc1tpXS50YWdzIHx8IG51bGxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWQubGVuZ3RoID8gY2xpcHBlZCA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGNsaXBQb2ludHMoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcykge1xuICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBnZW9tZXRyeS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYSA9IGdlb21ldHJ5W2ldLFxuICAgICAgICAgICAgYWsgPSBhW2F4aXNdO1xuXG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcbiAgICB9XG4gICAgcmV0dXJuIHNsaWNlO1xufVxuXG5mdW5jdGlvbiBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCBjbG9zZWQpIHtcblxuICAgIHZhciBzbGljZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgYWsgPSAwLFxuICAgICAgICAgICAgYmsgPSAwLFxuICAgICAgICAgICAgYiA9IG51bGwsXG4gICAgICAgICAgICBwb2ludHMgPSBnZW9tZXRyeVtpXSxcbiAgICAgICAgICAgIGFyZWEgPSBwb2ludHMuYXJlYSxcbiAgICAgICAgICAgIGRpc3QgPSBwb2ludHMuZGlzdCxcbiAgICAgICAgICAgIGxlbiA9IHBvaW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhLCBqO1xuXG4gICAgICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW4gLSAxOyBqKyspIHtcbiAgICAgICAgICAgIGEgPSBiIHx8IHBvaW50c1tqXTtcbiAgICAgICAgICAgIGIgPSBwb2ludHNbaiArIDFdO1xuICAgICAgICAgICAgYWsgPSBiayB8fCBhW2F4aXNdO1xuICAgICAgICAgICAgYmsgPSBiW2F4aXNdO1xuXG4gICAgICAgICAgICBpZiAoYWsgPCBrMSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKChiayA+IGsyKSkgeyAvLyAtLS18LS0tLS18LS0+XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSwgaW50ZXJzZWN0KGEsIGIsIGsyKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+PSBrMSkgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazEpKTsgLy8gLS0tfC0tPiAgfFxuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFrID4gazIpIHtcblxuICAgICAgICAgICAgICAgIGlmICgoYmsgPCBrMSkpIHsgLy8gPC0tfC0tLS0tfC0tLVxuICAgICAgICAgICAgICAgICAgICBzbGljZS5wdXNoKGludGVyc2VjdChhLCBiLCBrMiksIGludGVyc2VjdChhLCBiLCBrMSkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb3NlZCkgc2xpY2UgPSBuZXdTbGljZShzbGljZXMsIHNsaWNlLCBhcmVhLCBkaXN0KTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmsgPD0gazIpIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsyKSk7IC8vIHwgIDwtLXwtLS1cblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goYSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYmsgPCBrMSkgeyAvLyA8LS18LS0tICB8XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+IGsyKSB7IC8vIHwgIC0tLXwtLT5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjbG9zZWQpIHNsaWNlID0gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHwgLS0+IHxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkZCB0aGUgbGFzdCBwb2ludFxuICAgICAgICBhID0gcG9pbnRzW2xlbiAtIDFdO1xuICAgICAgICBhayA9IGFbYXhpc107XG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcblxuICAgICAgICAvLyBjbG9zZSB0aGUgcG9seWdvbiBpZiBpdHMgZW5kcG9pbnRzIGFyZSBub3QgdGhlIHNhbWUgYWZ0ZXIgY2xpcHBpbmdcbiAgICAgICAgaWYgKGNsb3NlZCAmJiBzbGljZVswXSAhPT0gc2xpY2Vbc2xpY2UubGVuZ3RoIC0gMV0pIHNsaWNlLnB1c2goc2xpY2VbMF0pO1xuXG4gICAgICAgIC8vIGFkZCB0aGUgZmluYWwgc2xpY2VcbiAgICAgICAgbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWNlcztcbn1cblxuZnVuY3Rpb24gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCkge1xuICAgIGlmIChzbGljZS5sZW5ndGgpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3QgcmVjYWxjdWxhdGUgdGhlIGFyZWEvbGVuZ3RoIG9mIHRoZSB1bmNsaXBwZWQgZ2VvbWV0cnkgYmVjYXVzZSB0aGUgY2FzZSB3aGVyZSBpdCBnb2VzXG4gICAgICAgIC8vIGJlbG93IHRoZSB2aXNpYmlsaXR5IHRocmVzaG9sZCBhcyBhIHJlc3VsdCBvZiBjbGlwcGluZyBpcyByYXJlLCBzbyB3ZSBhdm9pZCBkb2luZyB1bm5lY2Vzc2FyeSB3b3JrXG4gICAgICAgIHNsaWNlLmFyZWEgPSBhcmVhO1xuICAgICAgICBzbGljZS5kaXN0ID0gZGlzdDtcblxuICAgICAgICBzbGljZXMucHVzaChzbGljZSk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXJ0O1xuXG52YXIgc2ltcGxpZnkgPSByZXF1aXJlKCcuL3NpbXBsaWZ5Jyk7XG5cbi8vIGNvbnZlcnRzIEdlb0pTT04gZmVhdHVyZSBpbnRvIGFuIGludGVybWVkaWF0ZSBwcm9qZWN0ZWQgSlNPTiB2ZWN0b3IgZm9ybWF0IHdpdGggc2ltcGxpZmljYXRpb24gZGF0YVxuXG5mdW5jdGlvbiBjb252ZXJ0KGRhdGEsIHRvbGVyYW5jZSkge1xuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEuZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnZlcnRGZWF0dXJlKGZlYXR1cmVzLCBkYXRhLmZlYXR1cmVzW2ldLCB0b2xlcmFuY2UpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdGZWF0dXJlJykge1xuICAgICAgICBjb252ZXJ0RmVhdHVyZShmZWF0dXJlcywgZGF0YSwgdG9sZXJhbmNlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNpbmdsZSBnZW9tZXRyeSBvciBhIGdlb21ldHJ5IGNvbGxlY3Rpb25cbiAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtnZW9tZXRyeTogZGF0YX0sIHRvbGVyYW5jZSk7XG4gICAgfVxuICAgIHJldHVybiBmZWF0dXJlcztcbn1cblxuZnVuY3Rpb24gY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIGZlYXR1cmUsIHRvbGVyYW5jZSkge1xuICAgIHZhciBnZW9tID0gZmVhdHVyZS5nZW9tZXRyeSxcbiAgICAgICAgdHlwZSA9IGdlb20udHlwZSxcbiAgICAgICAgY29vcmRzID0gZ2VvbS5jb29yZGluYXRlcyxcbiAgICAgICAgdGFncyA9IGZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgaSwgaiwgcmluZ3M7XG5cbiAgICBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBbcHJvamVjdFBvaW50KGNvb3JkcyldKSk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdNdWx0aVBvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBwcm9qZWN0KGNvb3JkcykpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0xpbmVTdHJpbmcnKSB7XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIDIsIFtwcm9qZWN0KGNvb3JkcywgdG9sZXJhbmNlKV0pKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ011bHRpTGluZVN0cmluZycgfHwgdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIHJpbmdzID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmdzLnB1c2gocHJvamVjdChjb29yZHNbaV0sIHRvbGVyYW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIHR5cGUgPT09ICdQb2x5Z29uJyA/IDMgOiAyLCByaW5ncykpO1xuXG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICByaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29vcmRzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChwcm9qZWN0KGNvb3Jkc1tpXVtqXSwgdG9sZXJhbmNlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmVhdHVyZXMucHVzaChjcmVhdGUodGFncywgMywgcmluZ3MpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20uZ2VvbWV0cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeTogZ2VvbS5nZW9tZXRyaWVzW2ldLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHRhZ3NcbiAgICAgICAgICAgIH0sIHRvbGVyYW5jZSk7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVW5zdXBwb3J0ZWQgR2VvSlNPTiB0eXBlOiAnICsgZ2VvbS50eXBlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZSh0YWdzLCB0eXBlLCBnZW9tZXRyeSkge1xuICAgIHZhciBmZWF0dXJlID0ge1xuICAgICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIHRhZ3M6IHRhZ3MgfHwgbnVsbCxcbiAgICAgICAgbWluOiBbMSwgMV0sIC8vIGluaXRpYWwgYmJveCB2YWx1ZXM7XG4gICAgICAgIG1heDogWzAsIDBdICAvLyBub3RlIHRoYXQgYWxsIGNvb3JkcyBhcmUgaW4gWzAuLjFdIHJhbmdlXG4gICAgfTtcbiAgICBjYWxjQkJveChmZWF0dXJlKTtcbiAgICByZXR1cm4gZmVhdHVyZTtcbn1cblxuZnVuY3Rpb24gcHJvamVjdChsb25sYXRzLCB0b2xlcmFuY2UpIHtcbiAgICB2YXIgcHJvamVjdGVkID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb25sYXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByb2plY3RlZC5wdXNoKHByb2plY3RQb2ludChsb25sYXRzW2ldKSk7XG4gICAgfVxuICAgIGlmICh0b2xlcmFuY2UpIHtcbiAgICAgICAgc2ltcGxpZnkocHJvamVjdGVkLCB0b2xlcmFuY2UpO1xuICAgICAgICBjYWxjU2l6ZShwcm9qZWN0ZWQpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvamVjdGVkO1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0UG9pbnQocCkge1xuICAgIHZhciBzaW4gPSBNYXRoLnNpbihwWzFdICogTWF0aC5QSSAvIDE4MCksXG4gICAgICAgIHggPSAocFswXSAvIDM2MCArIDAuNSksXG4gICAgICAgIHkgPSAoMC41IC0gMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyBNYXRoLlBJKTtcbiAgICByZXR1cm4gW3gsIHksIDBdO1xufVxuXG4vLyBjYWxjdWxhdGUgYXJlYSBhbmQgbGVuZ3RoIG9mIHRoZSBwb2x5XG5mdW5jdGlvbiBjYWxjU2l6ZShwb2ludHMpIHtcbiAgICB2YXIgYXJlYSA9IDAsXG4gICAgICAgIGRpc3QgPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGEsIGI7IGkgPCBwb2ludHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGEgPSBiIHx8IHBvaW50c1tpXTtcbiAgICAgICAgYiA9IHBvaW50c1tpICsgMV07XG5cbiAgICAgICAgYXJlYSArPSBhWzBdICogYlsxXSAtIGJbMF0gKiBhWzFdO1xuXG4gICAgICAgIC8vIHVzZSBNYW5oYXR0YW4gZGlzdGFuY2UgaW5zdGVhZCBvZiBFdWNsaWRpYW4gb25lIHRvIGF2b2lkIGV4cGVuc2l2ZSBzcXVhcmUgcm9vdCBjb21wdXRhdGlvblxuICAgICAgICBkaXN0ICs9IE1hdGguYWJzKGJbMF0gLSBhWzBdKSArIE1hdGguYWJzKGJbMV0gLSBhWzFdKTtcbiAgICB9XG4gICAgcG9pbnRzLmFyZWEgPSBNYXRoLmFicyhhcmVhIC8gMik7XG4gICAgcG9pbnRzLmRpc3QgPSBkaXN0O1xufVxuXG4vLyBjYWxjdWxhdGUgdGhlIGZlYXR1cmUgYm91bmRpbmcgYm94IGZvciBmYXN0ZXIgY2xpcHBpbmcgbGF0ZXJcbmZ1bmN0aW9uIGNhbGNCQm94KGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICBtaW4gPSBmZWF0dXJlLm1pbixcbiAgICAgICAgbWF4ID0gZmVhdHVyZS5tYXg7XG5cbiAgICBpZiAoZmVhdHVyZS50eXBlID09PSAxKSBjYWxjUmluZ0JCb3gobWluLCBtYXgsIGdlb21ldHJ5KTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIGNhbGNSaW5nQkJveChtaW4sIG1heCwgZ2VvbWV0cnlbaV0pO1xuXG4gICAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGNhbGNSaW5nQkJveChtaW4sIG1heCwgcG9pbnRzKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcCA9IHBvaW50c1tpXTtcbiAgICAgICAgbWluWzBdID0gTWF0aC5taW4ocFswXSwgbWluWzBdKTtcbiAgICAgICAgbWF4WzBdID0gTWF0aC5tYXgocFswXSwgbWF4WzBdKTtcbiAgICAgICAgbWluWzFdID0gTWF0aC5taW4ocFsxXSwgbWluWzFdKTtcbiAgICAgICAgbWF4WzFdID0gTWF0aC5tYXgocFsxXSwgbWF4WzFdKTtcbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZ2VvanNvbnZ0O1xuXG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4vY29udmVydCcpLCAvLyBHZW9KU09OIGNvbnZlcnNpb24gYW5kIHByZXByb2Nlc3NpbmdcbiAgICBjbGlwID0gcmVxdWlyZSgnLi9jbGlwJyksICAgICAgIC8vIHN0cmlwZSBjbGlwcGluZyBhbGdvcml0aG1cbiAgICBjcmVhdGVUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7IC8vIGZpbmFsIHNpbXBsaWZpZWQgdGlsZSBnZW5lcmF0aW9uXG5cblxuZnVuY3Rpb24gZ2VvanNvbnZ0KGRhdGEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IEdlb0pTT05WVChkYXRhLCBvcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gR2VvSlNPTlZUKGRhdGEsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zID0gZXh0ZW5kKE9iamVjdC5jcmVhdGUodGhpcy5vcHRpb25zKSwgb3B0aW9ucyk7XG5cbiAgICB2YXIgZGVidWcgPSBvcHRpb25zLmRlYnVnO1xuXG4gICAgaWYgKGRlYnVnKSBjb25zb2xlLnRpbWUoJ3ByZXByb2Nlc3MgZGF0YScpO1xuXG4gICAgdmFyIHoyID0gMSA8PCBvcHRpb25zLmJhc2Vab29tLCAvLyAyXnpcbiAgICAgICAgZmVhdHVyZXMgPSBjb252ZXJ0KGRhdGEsIG9wdGlvbnMudG9sZXJhbmNlIC8gKHoyICogb3B0aW9ucy5leHRlbnQpKTtcblxuICAgIHRoaXMudGlsZXMgPSB7fTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoJ3ByZXByb2Nlc3MgZGF0YScpO1xuICAgICAgICBjb25zb2xlLnRpbWUoJ2dlbmVyYXRlIHRpbGVzIHVwIHRvIHonICsgb3B0aW9ucy5tYXhab29tKTtcbiAgICAgICAgdGhpcy5zdGF0cyA9IHt9O1xuICAgICAgICB0aGlzLnRvdGFsID0gMDtcbiAgICB9XG5cbiAgICAvLyBzdGFydCBzbGljaW5nIGZyb20gdGhlIHRvcCB0aWxlIGRvd25cbiAgICB0aGlzLnNwbGl0VGlsZShmZWF0dXJlcywgMCwgMCwgMCk7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2ZlYXR1cmVzOiAlZCwgcG9pbnRzOiAlZCcsIHRoaXMudGlsZXNbMF0ubnVtRmVhdHVyZXMsIHRoaXMudGlsZXNbMF0ubnVtUG9pbnRzKTtcbiAgICAgICAgY29uc29sZS50aW1lRW5kKCdnZW5lcmF0ZSB0aWxlcyB1cCB0byB6JyArIG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCd0aWxlcyBnZW5lcmF0ZWQ6JywgdGhpcy50b3RhbCwgSlNPTi5zdHJpbmdpZnkodGhpcy5zdGF0cykpO1xuICAgIH1cbn1cblxuR2VvSlNPTlZULnByb3RvdHlwZS5vcHRpb25zID0ge1xuICAgIGJhc2Vab29tOiAxNCwgICAvLyBtYXggem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgb25cbiAgICBtYXhab29tOiA0LCAgICAgLy8gem9vbSB0byBzbGljZSBkb3duIHRvIG9uIGZpcnN0IHBhc3NcbiAgICBtYXhQb2ludHM6IDEwMCwgLy8gc3RvcCBzbGljaW5nIGEgdGlsZSBiZWxvdyB0aGlzIG51bWJlciBvZiBwb2ludHNcbiAgICB0b2xlcmFuY2U6IDMsICAgLy8gc2ltcGxpZmljYXRpb24gdG9sZXJhbmNlIChoaWdoZXIgbWVhbnMgc2ltcGxlcilcbiAgICBleHRlbnQ6IDQwOTYsICAgLy8gdGlsZSBleHRlbnRcbiAgICBidWZmZXI6IDY0LCAgICAgLy8gdGlsZSBidWZmZXIgb24gZWFjaCBzaWRlXG4gICAgZGVidWc6IDAgICAgICAgIC8vIGxvZ2dpbmcgbGV2ZWwgKDAsIDEgb3IgMilcbn07XG5cbkdlb0pTT05WVC5wcm90b3R5cGUuc3BsaXRUaWxlID0gZnVuY3Rpb24gKGZlYXR1cmVzLCB6LCB4LCB5LCBjeiwgY3gsIGN5KSB7XG5cbiAgICB2YXIgc3RhY2sgPSBbZmVhdHVyZXMsIHosIHgsIHldLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICBkZWJ1ZyA9IG9wdGlvbnMuZGVidWcsXG4gICAgICAgIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50LFxuICAgICAgICBidWZmZXIgPSBvcHRpb25zLmJ1ZmZlcjtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHByb2Nlc3NpbmcgcXVldWVcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoKSB7XG4gICAgICAgIGZlYXR1cmVzID0gc3RhY2suc2hpZnQoKTtcbiAgICAgICAgeiA9IHN0YWNrLnNoaWZ0KCk7XG4gICAgICAgIHggPSBzdGFjay5zaGlmdCgpO1xuICAgICAgICB5ID0gc3RhY2suc2hpZnQoKTtcblxuICAgICAgICB2YXIgejIgPSAxIDw8IHosXG4gICAgICAgICAgICBpZCA9IHRvSUQoeiwgeCwgeSksXG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF0sXG4gICAgICAgICAgICB0aWxlVG9sZXJhbmNlID0geiA9PT0gb3B0aW9ucy5iYXNlWm9vbSA/IDAgOiBvcHRpb25zLnRvbGVyYW5jZSAvICh6MiAqIGV4dGVudCk7XG5cbiAgICAgICAgaWYgKCF0aWxlKSB7XG4gICAgICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NyZWF0aW9uJyk7XG5cbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLnRpbGVzW2lkXSA9IGNyZWF0ZVRpbGUoZmVhdHVyZXMsIHoyLCB4LCB5LCB0aWxlVG9sZXJhbmNlLCBleHRlbnQsIHogPT09IG9wdGlvbnMuYmFzZVpvb20pO1xuXG4gICAgICAgICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVidWcgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCd0aWxlIHolZC0lZC0lZCAoZmVhdHVyZXM6ICVkLCBwb2ludHM6ICVkLCBzaW1wbGlmaWVkOiAlZCknLFxuICAgICAgICAgICAgICAgICAgICAgICAgeiwgeCwgeSwgdGlsZS5udW1GZWF0dXJlcywgdGlsZS5udW1Qb2ludHMsIHRpbGUubnVtU2ltcGxpZmllZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZCgnY3JlYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICd6JyArIHogKyAnOic7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0c1trZXldID0gKHRoaXMuc3RhdHNba2V5XSB8fCAwKSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy50b3RhbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjeiAmJiAoeiA9PT0gb3B0aW9ucy5tYXhab29tIHx8IHRpbGUubnVtUG9pbnRzIDw9IG9wdGlvbnMubWF4UG9pbnRzIHx8XG4gICAgICAgICAgICAgICAgaXNDbGlwcGVkU3F1YXJlKHRpbGUuZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSkgfHwgeiA9PT0gb3B0aW9ucy5iYXNlWm9vbSB8fCB6ID09PSBjeikge1xuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSBmZWF0dXJlcztcbiAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBzdG9wIHRpbGluZ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN6KSB0aWxlLnNvdXJjZSA9IGZlYXR1cmVzO1xuICAgICAgICBlbHNlIHRpbGUuc291cmNlID0gbnVsbDtcblxuICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NsaXBwaW5nJyk7XG5cbiAgICAgICAgLy8gdmFsdWVzIHdlJ2xsIHVzZSBmb3IgY2xpcHBpbmdcbiAgICAgICAgdmFyIGsxID0gMC41ICogYnVmZmVyIC8gZXh0ZW50LFxuICAgICAgICAgICAgazIgPSAwLjUgLSBrMSxcbiAgICAgICAgICAgIGszID0gMC41ICsgazEsXG4gICAgICAgICAgICBrNCA9IDEgKyBrMSxcblxuICAgICAgICAgICAgdGwsIGJsLCB0ciwgYnIsIGxlZnQsIHJpZ2h0LFxuICAgICAgICAgICAgbSwgZ29MZWZ0LCBnb1RvcDtcblxuICAgICAgICBpZiAoY3opIHsgLy8gaWYgd2UgaGF2ZSBhIHNwZWNpZmljIHRpbGUgdG8gZHJpbGwgZG93biB0bywgY2FsY3VsYXRlIHdoZXJlIHRvIGdvXG4gICAgICAgICAgICBtID0gMSA8PCAoY3ogLSB6KTtcbiAgICAgICAgICAgIGdvTGVmdCA9IGN4IC8gbSAtIHggPCAwLjU7XG4gICAgICAgICAgICBnb1RvcCA9IGN5IC8gbSAtIHkgPCAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICB0bCA9IGJsID0gdHIgPSBiciA9IGxlZnQgPSByaWdodCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCFjeiB8fCAgZ29MZWZ0KSBsZWZ0ICA9IGNsaXAoZmVhdHVyZXMsIHoyLCB4IC0gazEsIHggKyBrMywgMCwgaW50ZXJzZWN0WCk7XG4gICAgICAgIGlmICghY3ogfHwgIWdvTGVmdCkgcmlnaHQgPSBjbGlwKGZlYXR1cmVzLCB6MiwgeCArIGsyLCB4ICsgazQsIDAsIGludGVyc2VjdFgpO1xuXG4gICAgICAgIGlmIChsZWZ0KSB7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICBnb1RvcCkgdGwgPSBjbGlwKGxlZnQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYmwgPSBjbGlwKGxlZnQsIHoyLCB5ICsgazIsIHkgKyBrNCwgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgIGlmICghY3ogfHwgIGdvVG9wKSB0ciA9IGNsaXAocmlnaHQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYnIgPSBjbGlwKHJpZ2h0LCB6MiwgeSArIGsyLCB5ICsgazQsIDEsIGludGVyc2VjdFkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS50aW1lRW5kKCdjbGlwcGluZycpO1xuXG4gICAgICAgIGlmICh0bCkgc3RhY2sucHVzaCh0bCwgeiArIDEsIHggKiAyLCAgICAgeSAqIDIpO1xuICAgICAgICBpZiAoYmwpIHN0YWNrLnB1c2goYmwsIHogKyAxLCB4ICogMiwgICAgIHkgKiAyICsgMSk7XG4gICAgICAgIGlmICh0cikgc3RhY2sucHVzaCh0ciwgeiArIDEsIHggKiAyICsgMSwgeSAqIDIpO1xuICAgICAgICBpZiAoYnIpIHN0YWNrLnB1c2goYnIsIHogKyAxLCB4ICogMiArIDEsIHkgKiAyICsgMSk7XG4gICAgfVxufTtcblxuR2VvSlNPTlZULnByb3RvdHlwZS5nZXRUaWxlID0gZnVuY3Rpb24gKHosIHgsIHkpIHtcbiAgICB2YXIgaWQgPSB0b0lEKHosIHgsIHkpO1xuICAgIGlmICh0aGlzLnRpbGVzW2lkXSkgcmV0dXJuIHRoaXMudGlsZXNbaWRdO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgIGRlYnVnID0gb3B0aW9ucy5kZWJ1ZztcblxuICAgIGlmIChkZWJ1ZyA+IDEpIGNvbnNvbGUubG9nKCdkcmlsbGluZyBkb3duIHRvIHolZC0lZC0lZCcsIHosIHgsIHkpO1xuXG4gICAgdmFyIHowID0geixcbiAgICAgICAgeDAgPSB4LFxuICAgICAgICB5MCA9IHksXG4gICAgICAgIHBhcmVudDtcblxuICAgIHdoaWxlICghcGFyZW50ICYmIHowID4gMCkge1xuICAgICAgICB6MC0tO1xuICAgICAgICB4MCA9IE1hdGguZmxvb3IoeDAgLyAyKTtcbiAgICAgICAgeTAgPSBNYXRoLmZsb29yKHkwIC8gMik7XG4gICAgICAgIHBhcmVudCA9IHRoaXMudGlsZXNbdG9JRCh6MCwgeDAsIHkwKV07XG4gICAgfVxuXG4gICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS5sb2coJ2ZvdW5kIHBhcmVudCB0aWxlIHolZC0lZC0lZCcsIHowLCB4MCwgeTApO1xuXG4gICAgLy8gaWYgd2UgZm91bmQgYSBwYXJlbnQgdGlsZSBjb250YWluaW5nIHRoZSBvcmlnaW5hbCBnZW9tZXRyeSwgd2UgY2FuIGRyaWxsIGRvd24gZnJvbSBpdFxuICAgIGlmIChwYXJlbnQuc291cmNlKSB7XG4gICAgICAgIGlmIChpc0NsaXBwZWRTcXVhcmUocGFyZW50LmZlYXR1cmVzLCBvcHRpb25zLmV4dGVudCwgb3B0aW9ucy5idWZmZXIpKSByZXR1cm4gcGFyZW50O1xuXG4gICAgICAgIGlmIChkZWJ1ZykgY29uc29sZS50aW1lKCdkcmlsbGluZyBkb3duJyk7XG4gICAgICAgIHRoaXMuc3BsaXRUaWxlKHBhcmVudC5zb3VyY2UsIHowLCB4MCwgeTAsIHosIHgsIHkpO1xuICAgICAgICBpZiAoZGVidWcpIGNvbnNvbGUudGltZUVuZCgnZHJpbGxpbmcgZG93bicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRpbGVzW2lkXTtcbn07XG5cbi8vIGNoZWNrcyB3aGV0aGVyIGEgdGlsZSBpcyBhIHdob2xlLWFyZWEgZmlsbCBhZnRlciBjbGlwcGluZzsgaWYgaXQgaXMsIHRoZXJlJ3Mgbm8gc2Vuc2Ugc2xpY2luZyBpdCBmdXJ0aGVyXG5mdW5jdGlvbiBpc0NsaXBwZWRTcXVhcmUoZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSB7XG4gICAgaWYgKGZlYXR1cmVzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1swXTtcbiAgICBpZiAoZmVhdHVyZS50eXBlICE9PSAzIHx8IGZlYXR1cmUuZ2VvbWV0cnkubGVuZ3RoID4gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlLmdlb21ldHJ5WzBdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwID0gZmVhdHVyZS5nZW9tZXRyeVswXVtpXTtcbiAgICAgICAgaWYgKChwWzBdICE9PSAtYnVmZmVyICYmIHBbMF0gIT09IGV4dGVudCArIGJ1ZmZlcikgfHxcbiAgICAgICAgICAgIChwWzFdICE9PSAtYnVmZmVyICYmIHBbMV0gIT09IGV4dGVudCArIGJ1ZmZlcikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHRvSUQoeiwgeCwgeSkge1xuICAgIHJldHVybiAoKCgxIDw8IHopICogeSArIHgpICogMzIpICsgejtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0WChhLCBiLCB4KSB7XG4gICAgcmV0dXJuIFt4LCAoeCAtIGFbMF0pICogKGJbMV0gLSBhWzFdKSAvIChiWzBdIC0gYVswXSkgKyBhWzFdLCAxXTtcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFkoYSwgYiwgeSkge1xuICAgIHJldHVybiBbKHkgLSBhWzFdKSAqIChiWzBdIC0gYVswXSkgLyAoYlsxXSAtIGFbMV0pICsgYVswXSwgeSwgMV07XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMpIHtcbiAgICBmb3IgKHZhciBpIGluIHNyYykgZGVzdFtpXSA9IHNyY1tpXTtcbiAgICByZXR1cm4gZGVzdDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBzaW1wbGlmeTtcblxuLy8gY2FsY3VsYXRlIHNpbXBsaWZpY2F0aW9uIGRhdGEgdXNpbmcgb3B0aW1pemVkIERvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1cblxuZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcblxuICAgIHZhciBzcVRvbGVyYW5jZSA9IHRvbGVyYW5jZSAqIHRvbGVyYW5jZSxcbiAgICAgICAgbGVuID0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgZmlyc3QgPSAwLFxuICAgICAgICBsYXN0ID0gbGVuIC0gMSxcbiAgICAgICAgc3RhY2sgPSBbXSxcbiAgICAgICAgaSwgbWF4U3FEaXN0LCBzcURpc3QsIGluZGV4O1xuXG4gICAgLy8gYWx3YXlzIHJldGFpbiB0aGUgZW5kcG9pbnRzICgxIGlzIHRoZSBtYXggdmFsdWUpXG4gICAgcG9pbnRzW2ZpcnN0XVsyXSA9IDE7XG4gICAgcG9pbnRzW2xhc3RdWzJdID0gMTtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHN0YWNrXG4gICAgd2hpbGUgKGxhc3QpIHtcblxuICAgICAgICBtYXhTcURpc3QgPSAwO1xuXG4gICAgICAgIGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgc3FEaXN0ID0gZ2V0U3FTZWdEaXN0KHBvaW50c1tpXSwgcG9pbnRzW2ZpcnN0XSwgcG9pbnRzW2xhc3RdKTtcblxuICAgICAgICAgICAgaWYgKHNxRGlzdCA+IG1heFNxRGlzdCkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBtYXhTcURpc3QgPSBzcURpc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4U3FEaXN0ID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHBvaW50c1tpbmRleF1bMl0gPSBtYXhTcURpc3Q7IC8vIHNhdmUgdGhlIHBvaW50IGltcG9ydGFuY2UgaW4gc3F1YXJlZCBwaXhlbHMgYXMgYSB6IGNvb3JkaW5hdGVcbiAgICAgICAgICAgIHN0YWNrLnB1c2goZmlyc3QsIGluZGV4LCBpbmRleCwgbGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXN0ID0gc3RhY2sucG9wKCk7XG4gICAgICAgIGZpcnN0ID0gc3RhY2sucG9wKCk7XG4gICAgfVxufVxuXG4vLyBzcXVhcmUgZGlzdGFuY2UgZnJvbSBhIHBvaW50IHRvIGEgc2VnbWVudFxuZnVuY3Rpb24gZ2V0U3FTZWdEaXN0KHAsIGEsIGIpIHtcblxuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sXG4gICAgICAgIGJ4ID0gYlswXSwgYnkgPSBiWzFdLFxuICAgICAgICBweCA9IHBbMF0sIHB5ID0gcFsxXSxcbiAgICAgICAgZHggPSBieCAtIHgsXG4gICAgICAgIGR5ID0gYnkgLSB5O1xuXG4gICAgaWYgKGR4ICE9PSAwIHx8IGR5ICE9PSAwKSB7XG5cbiAgICAgICAgdmFyIHQgPSAoKHB4IC0geCkgKiBkeCArIChweSAtIHkpICogZHkpIC8gKGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZiAodCA+IDEpIHtcbiAgICAgICAgICAgIHggPSBieDtcbiAgICAgICAgICAgIHkgPSBieTtcblxuICAgICAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICAgICAgICB4ICs9IGR4ICogdDtcbiAgICAgICAgICAgIHkgKz0gZHkgKiB0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHggPSBweCAtIHg7XG4gICAgZHkgPSBweSAtIHk7XG5cbiAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGlsZTtcblxuZnVuY3Rpb24gY3JlYXRlVGlsZShmZWF0dXJlcywgejIsIHR4LCB0eSwgdG9sZXJhbmNlLCBleHRlbnQsIG5vU2ltcGxpZnkpIHtcbiAgICB2YXIgdGlsZSA9IHtcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgICBudW1Qb2ludHM6IDAsXG4gICAgICAgIG51bVNpbXBsaWZpZWQ6IDAsXG4gICAgICAgIG51bUZlYXR1cmVzOiAwLFxuICAgICAgICBzb3VyY2U6IG51bGxcbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGlsZS5udW1GZWF0dXJlcysrO1xuICAgICAgICBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmVzW2ldLCB6MiwgdHgsIHR5LCB0b2xlcmFuY2UsIGV4dGVudCwgbm9TaW1wbGlmeSk7XG4gICAgfVxuICAgIHJldHVybiB0aWxlO1xufVxuXG5mdW5jdGlvbiBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmUsIHoyLCB0eCwgdHksIHRvbGVyYW5jZSwgZXh0ZW50LCBub1NpbXBsaWZ5KSB7XG5cbiAgICB2YXIgZ2VvbSA9IGZlYXR1cmUuZ2VvbWV0cnksXG4gICAgICAgIHR5cGUgPSBmZWF0dXJlLnR5cGUsXG4gICAgICAgIHRyYW5zZm9ybWVkID0gW10sXG4gICAgICAgIHNxVG9sZXJhbmNlID0gdG9sZXJhbmNlICogdG9sZXJhbmNlLFxuICAgICAgICBpLCBqLCByaW5nLCBwO1xuXG4gICAgaWYgKHR5cGUgPT09IDEpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWVkLnB1c2godHJhbnNmb3JtUG9pbnQoZ2VvbVtpXSwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgdGlsZS5udW1TaW1wbGlmaWVkKys7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gc2ltcGxpZnkgYW5kIHRyYW5zZm9ybSBwcm9qZWN0ZWQgY29vcmRpbmF0ZXMgZm9yIHRpbGUgZ2VvbWV0cnlcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmcgPSBnZW9tW2ldO1xuXG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHRpbnkgcG9seWxpbmVzICYgcG9seWdvbnNcbiAgICAgICAgICAgIGlmICghbm9TaW1wbGlmeSAmJiAoKHR5cGUgPT09IDIgJiYgcmluZy5kaXN0IDwgdG9sZXJhbmNlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodHlwZSA9PT0gMyAmJiByaW5nLmFyZWEgPCBzcVRvbGVyYW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgdGlsZS5udW1Qb2ludHMgKz0gcmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZFJpbmcgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcmluZ1tqXTtcbiAgICAgICAgICAgICAgICAvLyBrZWVwIHBvaW50cyB3aXRoIGltcG9ydGFuY2UgPiB0b2xlcmFuY2VcbiAgICAgICAgICAgICAgICBpZiAobm9TaW1wbGlmeSB8fCBwWzJdID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRSaW5nLnB1c2godHJhbnNmb3JtUG9pbnQocCwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICAgICAgICAgIHRpbGUubnVtU2ltcGxpZmllZCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cmFuc2Zvcm1lZC5wdXNoKHRyYW5zZm9ybWVkUmluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNmb3JtZWQubGVuZ3RoKSB7XG4gICAgICAgIHRpbGUuZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICBnZW9tZXRyeTogdHJhbnNmb3JtZWQsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgdGFnczogZmVhdHVyZS50YWdzIHx8IG51bGxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludChwLCB6MiwgdHgsIHR5LCBleHRlbnQpIHtcbiAgICB2YXIgeCA9IE1hdGgucm91bmQoZXh0ZW50ICogKHBbMF0gKiB6MiAtIHR4KSksXG4gICAgICAgIHkgPSBNYXRoLnJvdW5kKGV4dGVudCAqIChwWzFdICogejIgLSB0eSkpO1xuICAgIHJldHVybiBbeCwgeV07XG59XG4iLCIvKipcbiAqIEBmaWxlb3ZlcnZpZXcgZ2wtbWF0cml4IC0gSGlnaCBwZXJmb3JtYW5jZSBtYXRyaXggYW5kIHZlY3RvciBvcGVyYXRpb25zXG4gKiBAYXV0aG9yIEJyYW5kb24gSm9uZXNcbiAqIEBhdXRob3IgQ29saW4gTWFjS2VuemllIElWXG4gKiBAdmVyc2lvbiAyLjIuMVxuICovXG5cbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbihmdW5jdGlvbihfZ2xvYmFsKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIHZhciBzaGltID0ge307XG4gIGlmICh0eXBlb2YoZXhwb3J0cykgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHt9O1xuICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gc2hpbS5leHBvcnRzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBhIGJyb3dzZXIsIGRlZmluZSBpdHMgbmFtZXNwYWNlcyBpbiBnbG9iYWxcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHR5cGVvZih3aW5kb3cpICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IF9nbG9iYWw7XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBjb21tb25qcywgZGVmaW5lIGl0cyBuYW1lc3BhY2VzIGluIGV4cG9ydHNcbiAgICBzaGltLmV4cG9ydHMgPSBleHBvcnRzO1xuICB9XG5cbiAgKGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAvKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbmlmKCFHTE1BVF9FUFNJTE9OKSB7XG4gICAgdmFyIEdMTUFUX0VQU0lMT04gPSAwLjAwMDAwMTtcbn1cblxuaWYoIUdMTUFUX0FSUkFZX1RZUEUpIHtcbiAgICB2YXIgR0xNQVRfQVJSQVlfVFlQRSA9ICh0eXBlb2YgRmxvYXQzMkFycmF5ICE9PSAndW5kZWZpbmVkJykgPyBGbG9hdDMyQXJyYXkgOiBBcnJheTtcbn1cblxuaWYoIUdMTUFUX1JBTkRPTSkge1xuICAgIHZhciBHTE1BVF9SQU5ET00gPSBNYXRoLnJhbmRvbTtcbn1cblxuLyoqXG4gKiBAY2xhc3MgQ29tbW9uIHV0aWxpdGllc1xuICogQG5hbWUgZ2xNYXRyaXhcbiAqL1xudmFyIGdsTWF0cml4ID0ge307XG5cbi8qKlxuICogU2V0cyB0aGUgdHlwZSBvZiBhcnJheSB1c2VkIHdoZW4gY3JlYXRpbmcgbmV3IHZlY3RvcnMgYW5kIG1hdHJpY2llc1xuICpcbiAqIEBwYXJhbSB7VHlwZX0gdHlwZSBBcnJheSB0eXBlLCBzdWNoIGFzIEZsb2F0MzJBcnJheSBvciBBcnJheVxuICovXG5nbE1hdHJpeC5zZXRNYXRyaXhBcnJheVR5cGUgPSBmdW5jdGlvbih0eXBlKSB7XG4gICAgR0xNQVRfQVJSQVlfVFlQRSA9IHR5cGU7XG59XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLmdsTWF0cml4ID0gZ2xNYXRyaXg7XG59XG5cbnZhciBkZWdyZWUgPSBNYXRoLlBJIC8gMTgwO1xuXG4vKipcbiogQ29udmVydCBEZWdyZWUgVG8gUmFkaWFuXG4qXG4qIEBwYXJhbSB7TnVtYmVyfSBBbmdsZSBpbiBEZWdyZWVzXG4qL1xuZ2xNYXRyaXgudG9SYWRpYW4gPSBmdW5jdGlvbihhKXtcbiAgICAgcmV0dXJuIGEgKiBkZWdyZWU7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyIERpbWVuc2lvbmFsIFZlY3RvclxuICogQG5hbWUgdmVjMlxuICovXG5cbnZhciB2ZWMyID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldywgZW1wdHkgdmVjMlxuICpcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gMDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgyKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzIgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHkpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLmFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnN1YnRyYWN0ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAtIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnN1YnRyYWN0fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuc3ViID0gdmVjMi5zdWJ0cmFjdDtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICogYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5tdWwgPSB2ZWMyLm11bHRpcGx5O1xuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5kaXZpZGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC8gYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdIC8gYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIuZGl2aWRlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGl2ID0gdmVjMi5kaXZpZGU7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWluaW11bSBvZiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLm1pbiA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pO1xuICAgIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5tYXggPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1heChhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgYSB2ZWMyIGJ5IGEgc2NhbGFyIG51bWJlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiO1xuICAgIG91dFsxXSA9IGFbMV0gKiBiO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzIncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnNjYWxlQW5kQWRkID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBzY2FsZSkge1xuICAgIG91dFswXSA9IGFbMF0gKyAoYlswXSAqIHNjYWxlKTtcbiAgICBvdXRbMV0gPSBhWzFdICsgKGJbMV0gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzIuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdO1xuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5KTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLmRpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGlzdCA9IHZlYzIuZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG52ZWMyLnNxdWFyZWREaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLnNxckRpc3QgPSB2ZWMyLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMyLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMi5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5sZW4gPSB2ZWMyLmxlbmd0aDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG52ZWMyLnNxdWFyZWRMZW5ndGggPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5zcXJMZW4gPSB2ZWMyLnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMyLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV07XG59O1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMyJ3NcbiAqIE5vdGUgdGhhdCB0aGUgY3Jvc3MgcHJvZHVjdCBtdXN0IGJ5IGRlZmluaXRpb24gcHJvZHVjZSBhIDNEIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMi5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciB6ID0gYVswXSAqIGJbMV0gLSBhWzFdICogYlswXTtcbiAgICBvdXRbMF0gPSBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IHo7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV07XG4gICAgb3V0WzBdID0gYXggKyB0ICogKGJbMF0gLSBheCk7XG4gICAgb3V0WzFdID0gYXkgKyB0ICogKGJbMV0gLSBheSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5yYW5kb20gPSBmdW5jdGlvbiAob3V0LCBzY2FsZSkge1xuICAgIHNjYWxlID0gc2NhbGUgfHwgMS4wO1xuICAgIHZhciByID0gR0xNQVRfUkFORE9NKCkgKiAyLjAgKiBNYXRoLlBJO1xuICAgIG91dFswXSA9IE1hdGguY29zKHIpICogc2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiBzY2FsZTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQyfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDIgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHk7XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzNdICogeTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyZFxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0MmR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIudHJhbnNmb3JtTWF0MmQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDNcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzEnXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQzfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDMgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVszXSAqIHkgKyBtWzZdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs0XSAqIHkgKyBtWzddO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDRcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzAnXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCBcbiAgICAgICAgeSA9IGFbMV07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bMTJdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzEzXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjMnMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMi4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzJzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzIuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gdmVjIHZlY3RvciB0byByZXByZXNlbnQgYXMgYSBzdHJpbmdcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmVjdG9yXG4gKi9cbnZlYzIuc3RyID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gJ3ZlYzIoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzIgPSB2ZWMyO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgMyBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzNcbiAqL1xuXG52YXIgdmVjMyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbnZlYzMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDMpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMyBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMyk7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgzKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjMyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzIHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnNldCA9IGZ1bmN0aW9uKG91dCwgeCwgeSwgeikge1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnN1YiA9IHZlYzMuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubXVsID0gdmVjMy5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpdiA9IHZlYzMuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5kaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeik7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpc3QgPSB2ZWMzLmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl07XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqejtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckRpc3QgPSB2ZWMzLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMzLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl07XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnopO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubGVuID0gdmVjMy5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjMy5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMuc3F1YXJlZExlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckxlbiA9IHZlYzMuc3F1YXJlZExlbmd0aDtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm5lZ2F0ZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IC1hWzBdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5ub3JtYWxpemUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5ICsgeip6O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMzLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTtcbn07XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdO1xuXG4gICAgb3V0WzBdID0gYXkgKiBieiAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV0sXG4gICAgICAgIGF6ID0gYVsyXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICB2YXIgciA9IEdMTUFUX1JBTkRPTSgpICogMi4wICogTWF0aC5QSTtcbiAgICB2YXIgeiA9IChHTE1BVF9SQU5ET00oKSAqIDIuMCkgLSAxLjA7XG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlO1xuXG4gICAgb3V0WzBdID0gTWF0aC5jb3MocikgKiB6U2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiB6U2NhbGU7XG4gICAgb3V0WzJdID0geiAqIHNjYWxlO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl07XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM107XG4gICAgb3V0WzJdID0gbVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMudHJhbnNmb3JtTWF0MyA9IGZ1bmN0aW9uKG91dCwgYSwgbSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdO1xuICAgIG91dFswXSA9IHggKiBtWzBdICsgeSAqIG1bM10gKyB6ICogbVs2XTtcbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN107XG4gICAgb3V0WzJdID0geCAqIG1bMl0gKyB5ICogbVs1XSArIHogKiBtWzhdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnRyYW5zZm9ybVF1YXQgPSBmdW5jdGlvbihvdXQsIGEsIHEpIHtcbiAgICAvLyBiZW5jaG1hcmtzOiBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXRyYW5zZm9ybS12ZWMzLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl0sXG4gICAgICAgIHF4ID0gcVswXSwgcXkgPSBxWzFdLCBxeiA9IHFbMl0sIHF3ID0gcVszXSxcblxuICAgICAgICAvLyBjYWxjdWxhdGUgcXVhdCAqIHZlY1xuICAgICAgICBpeCA9IHF3ICogeCArIHF5ICogeiAtIHF6ICogeSxcbiAgICAgICAgaXkgPSBxdyAqIHkgKyBxeiAqIHggLSBxeCAqIHosXG4gICAgICAgIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4LFxuICAgICAgICBpdyA9IC1xeCAqIHggLSBxeSAqIHkgLSBxeiAqIHo7XG5cbiAgICAvLyBjYWxjdWxhdGUgcmVzdWx0ICogaW52ZXJzZSBxdWF0XG4gICAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeTtcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6O1xuICAgIG91dFsyXSA9IGl6ICogcXcgKyBpdyAqIC1xeiArIGl4ICogLXF5IC0gaXkgKiAtcXg7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHgtYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVggPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICAgdmFyIHAgPSBbXSwgcj1bXTtcblx0ICAvL1RyYW5zbGF0ZSBwb2ludCB0byB0aGUgb3JpZ2luXG5cdCAgcFswXSA9IGFbMF0gLSBiWzBdO1xuXHQgIHBbMV0gPSBhWzFdIC0gYlsxXTtcbiAgXHRwWzJdID0gYVsyXSAtIGJbMl07XG5cblx0ICAvL3BlcmZvcm0gcm90YXRpb25cblx0ICByWzBdID0gcFswXTtcblx0ICByWzFdID0gcFsxXSpNYXRoLmNvcyhjKSAtIHBbMl0qTWF0aC5zaW4oYyk7XG5cdCAgclsyXSA9IHBbMV0qTWF0aC5zaW4oYykgKyBwWzJdKk1hdGguY29zKGMpO1xuXG5cdCAgLy90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuXHQgIG91dFswXSA9IHJbMF0gKyBiWzBdO1xuXHQgIG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuXHQgIG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuXG4gIFx0cmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHktYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVkgPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICBcdHZhciBwID0gW10sIHI9W107XG4gIFx0Ly9UcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICBcdHBbMF0gPSBhWzBdIC0gYlswXTtcbiAgXHRwWzFdID0gYVsxXSAtIGJbMV07XG4gIFx0cFsyXSA9IGFbMl0gLSBiWzJdO1xuICBcbiAgXHQvL3BlcmZvcm0gcm90YXRpb25cbiAgXHRyWzBdID0gcFsyXSpNYXRoLnNpbihjKSArIHBbMF0qTWF0aC5jb3MoYyk7XG4gIFx0clsxXSA9IHBbMV07XG4gIFx0clsyXSA9IHBbMl0qTWF0aC5jb3MoYykgLSBwWzBdKk1hdGguc2luKGMpO1xuICBcbiAgXHQvL3RyYW5zbGF0ZSB0byBjb3JyZWN0IHBvc2l0aW9uXG4gIFx0b3V0WzBdID0gclswXSArIGJbMF07XG4gIFx0b3V0WzFdID0gclsxXSArIGJbMV07XG4gIFx0b3V0WzJdID0gclsyXSArIGJbMl07XG4gIFxuICBcdHJldHVybiBvdXQ7XG59O1xuXG4vKlxuKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB6LWF4aXNcbiogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4qIEBwYXJhbSB7dmVjM30gYSBUaGUgdmVjMyBwb2ludCB0byByb3RhdGVcbiogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4qIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuKiBAcmV0dXJucyB7dmVjM30gb3V0XG4qL1xudmVjMy5yb3RhdGVaID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBjKXtcbiAgXHR2YXIgcCA9IFtdLCByPVtdO1xuICBcdC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgXHRwWzBdID0gYVswXSAtIGJbMF07XG4gIFx0cFsxXSA9IGFbMV0gLSBiWzFdO1xuICBcdHBbMl0gPSBhWzJdIC0gYlsyXTtcbiAgXG4gIFx0Ly9wZXJmb3JtIHJvdGF0aW9uXG4gIFx0clswXSA9IHBbMF0qTWF0aC5jb3MoYykgLSBwWzFdKk1hdGguc2luKGMpO1xuICBcdHJbMV0gPSBwWzBdKk1hdGguc2luKGMpICsgcFsxXSpNYXRoLmNvcyhjKTtcbiAgXHRyWzJdID0gcFsyXTtcbiAgXG4gIFx0Ly90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuICBcdG91dFswXSA9IHJbMF0gKyBiWzBdO1xuICBcdG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuICBcdG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuICBcbiAgXHRyZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjM3MuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMy4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzNzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzMuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07IHZlY1syXSA9IGFbaSsyXTtcbiAgICAgICAgICAgIGZuKHZlYywgdmVjLCBhcmcpO1xuICAgICAgICAgICAgYVtpXSA9IHZlY1swXTsgYVtpKzFdID0gdmVjWzFdOyBhW2krMl0gPSB2ZWNbMl07XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWMzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWMzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzMgPSB2ZWMzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNCBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzRcbiAqL1xuXG52YXIgdmVjNCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbnZlYzQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWM0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmZyb21WYWx1ZXMgPSBmdW5jdGlvbih4LCB5LCB6LCB3KSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIG91dFszXSA9IHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHksIHosIHcpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSB3O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICBvdXRbM10gPSBhWzNdICsgYlszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIG91dFszXSA9IGFbM10gLSBiWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LnN1YiA9IHZlYzQuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0Lm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAqIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubXVsID0gdmVjNC5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAvIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpdiA9IHZlYzQuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICBvdXRbM10gPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICBvdXRbM10gPSBhWzNdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICBvdXRbM10gPSBhWzNdICsgKGJbM10gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzQuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeiArIHcqdyk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpc3QgPSB2ZWM0LmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjNC5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6ICsgdyp3O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3F1YXJlZERpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuc3FyRGlzdCA9IHZlYzQuc3F1YXJlZERpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbnZlYzQubGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnogKyB3KncpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubGVuID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjNC5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqeiArIHcqdztcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjNC5zcXJMZW4gPSB2ZWM0LnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICBvdXRbMl0gPSAtYVsyXTtcbiAgICBvdXRbM10gPSAtYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl0sXG4gICAgICAgIHcgPSBhWzNdO1xuICAgIHZhciBsZW4gPSB4KnggKyB5KnkgKyB6KnogKyB3Knc7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pO1xuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuO1xuICAgICAgICBvdXRbMV0gPSBhWzFdICogbGVuO1xuICAgICAgICBvdXRbMl0gPSBhWzJdICogbGVuO1xuICAgICAgICBvdXRbM10gPSBhWzNdICogbGVuO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbnZlYzQuZG90ID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM107XG59O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LmxlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl0sXG4gICAgICAgIGF3ID0gYVszXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICAvL1RPRE86IFRoaXMgaXMgYSBwcmV0dHkgYXdmdWwgd2F5IG9mIGRvaW5nIHRoaXMuIEZpbmQgc29tZXRoaW5nIGJldHRlci5cbiAgICBvdXRbMF0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMV0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMl0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbM10gPSBHTE1BVF9SQU5ET00oKTtcbiAgICB2ZWM0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgdmVjNC5zY2FsZShvdXQsIG91dCwgc2NhbGUpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzQgd2l0aCBhIG1hdDQuXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnRyYW5zZm9ybU1hdDQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM107XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogdztcbiAgICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3O1xuICAgIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7cXVhdH0gcSBxdWF0ZXJuaW9uIHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQudHJhbnNmb3JtUXVhdCA9IGZ1bmN0aW9uKG91dCwgYSwgcSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLFxuICAgICAgICBxeCA9IHFbMF0sIHF5ID0gcVsxXSwgcXogPSBxWzJdLCBxdyA9IHFbM10sXG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHF1YXQgKiB2ZWNcbiAgICAgICAgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHksXG4gICAgICAgIGl5ID0gcXcgKiB5ICsgcXogKiB4IC0gcXggKiB6LFxuICAgICAgICBpeiA9IHF3ICogeiArIHF4ICogeSAtIHF5ICogeCxcbiAgICAgICAgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6O1xuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXk7XG4gICAgb3V0WzFdID0gaXkgKiBxdyArIGl3ICogLXF5ICsgaXogKiAtcXggLSBpeCAqIC1xejtcbiAgICBvdXRbMl0gPSBpeiAqIHF3ICsgaXcgKiAtcXogKyBpeCAqIC1xeSAtIGl5ICogLXF4O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFBlcmZvcm0gc29tZSBvcGVyYXRpb24gb3ZlciBhbiBhcnJheSBvZiB2ZWM0cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhIHRoZSBhcnJheSBvZiB2ZWN0b3JzIHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIHtOdW1iZXJ9IHN0cmlkZSBOdW1iZXIgb2YgZWxlbWVudHMgYmV0d2VlbiB0aGUgc3RhcnQgb2YgZWFjaCB2ZWM0LiBJZiAwIGFzc3VtZXMgdGlnaHRseSBwYWNrZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXQgTnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNraXAgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudCBOdW1iZXIgb2YgdmVjMnMgdG8gaXRlcmF0ZSBvdmVyLiBJZiAwIGl0ZXJhdGVzIG92ZXIgZW50aXJlIGFycmF5XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbYXJnXSBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHBhc3MgdG8gZm5cbiAqIEByZXR1cm5zIHtBcnJheX0gYVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuZm9yRWFjaCA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdmVjID0gdmVjNC5jcmVhdGUoKTtcblxuICAgIHJldHVybiBmdW5jdGlvbihhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGlmKCFzdHJpZGUpIHtcbiAgICAgICAgICAgIHN0cmlkZSA9IDQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZighb2Zmc2V0KSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGwgPSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gb2Zmc2V0OyBpIDwgbDsgaSArPSBzdHJpZGUpIHtcbiAgICAgICAgICAgIHZlY1swXSA9IGFbaV07IHZlY1sxXSA9IGFbaSsxXTsgdmVjWzJdID0gYVtpKzJdOyB2ZWNbM10gPSBhW2krM107XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTsgYVtpKzJdID0gdmVjWzJdOyBhW2krM10gPSB2ZWNbM107XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWM0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWM0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMudmVjNCA9IHZlYzQ7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDIgTWF0cml4XG4gKiBAbmFtZSBtYXQyXG4gKi9cblxudmFyIG1hdDIgPSB7fTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGlkZW50aXR5IG1hdDJcbiAqXG4gKiBAcmV0dXJucyB7bWF0Mn0gYSBuZXcgMngyIG1hdHJpeFxuICovXG5tYXQyLmNyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSAxO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSBtYXRyaXggdG8gY2xvbmVcbiAqIEByZXR1cm5zIHttYXQyfSBhIG5ldyAyeDIgbWF0cml4XG4gKi9cbm1hdDIuY2xvbmUgPSBmdW5jdGlvbihhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqL1xubWF0Mi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQyIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGExID0gYVsxXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYVsxXTtcbiAgICAgICAgb3V0WzNdID0gYVszXTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGEwICogYTMgLSBhMiAqIGExO1xuXG4gICAgaWYgKCFkZXQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcbiAgICBcbiAgICBvdXRbMF0gPSAgYTMgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWExICogZGV0O1xuICAgIG91dFsyXSA9IC1hMiAqIGRldDtcbiAgICBvdXRbM10gPSAgYTAgKiBkZXQ7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhZGp1Z2F0ZSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuYWRqb2ludCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIENhY2hpbmcgdGhpcyB2YWx1ZSBpcyBuZXNzZWNhcnkgaWYgb3V0ID09IGFcbiAgICB2YXIgYTAgPSBhWzBdO1xuICAgIG91dFswXSA9ICBhWzNdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIG91dFszXSA9ICBhMDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MlxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQyLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzJdICogYVsxXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MidzXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM107XG4gICAgdmFyIGIwID0gYlswXSwgYjEgPSBiWzFdLCBiMiA9IGJbMl0sIGIzID0gYlszXTtcbiAgICBvdXRbMF0gPSBhMCAqIGIwICsgYTIgKiBiMTtcbiAgICBvdXRbMV0gPSBhMSAqIGIwICsgYTMgKiBiMTtcbiAgICBvdXRbMl0gPSBhMCAqIGIyICsgYTIgKiBiMztcbiAgICBvdXRbM10gPSBhMSAqIGIyICsgYTMgKiBiMztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0Mi5tdWwgPSBtYXQyLm11bHRpcGx5O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQyIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIucm90YXRlID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICAgIG91dFswXSA9IGEwICogIGMgKyBhMiAqIHM7XG4gICAgb3V0WzFdID0gYTEgKiAgYyArIGEzICogcztcbiAgICBvdXRbMl0gPSBhMCAqIC1zICsgYTIgKiBjO1xuICAgIG91dFszXSA9IGExICogLXMgKyBhMyAqIGM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQyIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMyfSB2IHRoZSB2ZWMyIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqKi9cbm1hdDIuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIHYpIHtcbiAgICB2YXIgYTAgPSBhWzBdLCBhMSA9IGFbMV0sIGEyID0gYVsyXSwgYTMgPSBhWzNdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMCAqIHYwO1xuICAgIG91dFsxXSA9IGExICogdjA7XG4gICAgb3V0WzJdID0gYTIgKiB2MTtcbiAgICBvdXRbM10gPSBhMyAqIHYxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQyXG4gKlxuICogQHBhcmFtIHttYXQyfSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0Mi5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MignICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byBjYWxjdWxhdGUgRnJvYmVuaXVzIG5vcm0gb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IEZyb2Jlbml1cyBub3JtXG4gKi9cbm1hdDIuZnJvYiA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuKE1hdGguc3FydChNYXRoLnBvdyhhWzBdLCAyKSArIE1hdGgucG93KGFbMV0sIDIpICsgTWF0aC5wb3coYVsyXSwgMikgKyBNYXRoLnBvdyhhWzNdLCAyKSkpXG59O1xuXG4vKipcbiAqIFJldHVybnMgTCwgRCBhbmQgVSBtYXRyaWNlcyAoTG93ZXIgdHJpYW5ndWxhciwgRGlhZ29uYWwgYW5kIFVwcGVyIHRyaWFuZ3VsYXIpIGJ5IGZhY3Rvcml6aW5nIHRoZSBpbnB1dCBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gTCB0aGUgbG93ZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IEQgdGhlIGRpYWdvbmFsIG1hdHJpeCBcbiAqIEBwYXJhbSB7bWF0Mn0gVSB0aGUgdXBwZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIGlucHV0IG1hdHJpeCB0byBmYWN0b3JpemVcbiAqL1xuXG5tYXQyLkxEVSA9IGZ1bmN0aW9uIChMLCBELCBVLCBhKSB7IFxuICAgIExbMl0gPSBhWzJdL2FbMF07IFxuICAgIFVbMF0gPSBhWzBdOyBcbiAgICBVWzFdID0gYVsxXTsgXG4gICAgVVszXSA9IGFbM10gLSBMWzJdICogVVsxXTsgXG4gICAgcmV0dXJuIFtMLCBELCBVXTsgICAgICAgXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MiA9IG1hdDI7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDMgTWF0cml4XG4gKiBAbmFtZSBtYXQyZFxuICogXG4gKiBAZGVzY3JpcHRpb24gXG4gKiBBIG1hdDJkIGNvbnRhaW5zIHNpeCBlbGVtZW50cyBkZWZpbmVkIGFzOlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eV1cbiAqIDwvcHJlPlxuICogVGhpcyBpcyBhIHNob3J0IGZvcm0gZm9yIHRoZSAzeDMgbWF0cml4OlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eSxcbiAqICAwLCAwLCAxXVxuICogPC9wcmU+XG4gKiBUaGUgbGFzdCByb3cgaXMgaWdub3JlZCBzbyB0aGUgYXJyYXkgaXMgc2hvcnRlciBhbmQgb3BlcmF0aW9ucyBhcmUgZmFzdGVyLlxuICovXG5cbnZhciBtYXQyZCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0MmRcbiAqXG4gKiBAcmV0dXJucyB7bWF0MmR9IGEgbmV3IDJ4MyBtYXRyaXhcbiAqL1xubWF0MmQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MmQgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDJkfSBhIG5ldyAyeDMgbWF0cml4XG4gKi9cbm1hdDJkLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg2KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MmQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqL1xubWF0MmQuY29weSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCBhIG1hdDJkIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0MmR9IG91dFxuICovXG5tYXQyZC5pbnZlcnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYWEgPSBhWzBdLCBhYiA9IGFbMV0sIGFjID0gYVsyXSwgYWQgPSBhWzNdLFxuICAgICAgICBhdHggPSBhWzRdLCBhdHkgPSBhWzVdO1xuXG4gICAgdmFyIGRldCA9IGFhICogYWQgLSBhYiAqIGFjO1xuICAgIGlmKCFkZXQpe1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYWQgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWFiICogZGV0O1xuICAgIG91dFsyXSA9IC1hYyAqIGRldDtcbiAgICBvdXRbM10gPSBhYSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYWMgKiBhdHkgLSBhZCAqIGF0eCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKGFiICogYXR4IC0gYWEgKiBhdHkpICogZGV0O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MmRcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDJkLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzFdICogYVsyXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MmQnc1xuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyZH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBiMCA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM10sIGI0ID0gYls0XSwgYjUgPSBiWzVdO1xuICAgIG91dFswXSA9IGEwICogYjAgKyBhMiAqIGIxO1xuICAgIG91dFsxXSA9IGExICogYjAgKyBhMyAqIGIxO1xuICAgIG91dFsyXSA9IGEwICogYjIgKyBhMiAqIGIzO1xuICAgIG91dFszXSA9IGExICogYjIgKyBhMyAqIGIzO1xuICAgIG91dFs0XSA9IGEwICogYjQgKyBhMiAqIGI1ICsgYTQ7XG4gICAgb3V0WzVdID0gYTEgKiBiNCArIGEzICogYjUgKyBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDJkLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDJkLm11bCA9IG1hdDJkLm11bHRpcGx5O1xuXG5cbi8qKlxuICogUm90YXRlcyBhIG1hdDJkIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgb3V0WzBdID0gYTAgKiAgYyArIGEyICogcztcbiAgICBvdXRbMV0gPSBhMSAqICBjICsgYTMgKiBzO1xuICAgIG91dFsyXSA9IGEwICogLXMgKyBhMiAqIGM7XG4gICAgb3V0WzNdID0gYTEgKiAtcyArIGEzICogYztcbiAgICBvdXRbNF0gPSBhNDtcbiAgICBvdXRbNV0gPSBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDJkIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnNjYWxlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSwgYTQgPSBhWzRdLCBhNSA9IGFbNV0sXG4gICAgICAgIHYwID0gdlswXSwgdjEgPSB2WzFdO1xuICAgIG91dFswXSA9IGEwICogdjA7XG4gICAgb3V0WzFdID0gYTEgKiB2MDtcbiAgICBvdXRbMl0gPSBhMiAqIHYxO1xuICAgIG91dFszXSA9IGEzICogdjE7XG4gICAgb3V0WzRdID0gYTQ7XG4gICAgb3V0WzVdID0gYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNsYXRlcyB0aGUgbWF0MmQgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB0aGUgdmVjMiB0byB0cmFuc2xhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMDtcbiAgICBvdXRbMV0gPSBhMTtcbiAgICBvdXRbMl0gPSBhMjtcbiAgICBvdXRbM10gPSBhMztcbiAgICBvdXRbNF0gPSBhMCAqIHYwICsgYTIgKiB2MSArIGE0O1xuICAgIG91dFs1XSA9IGExICogdjAgKyBhMyAqIHYxICsgYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQyZC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MmQoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcsICcgKyBhWzJdICsgJywgJyArIFxuICAgICAgICAgICAgICAgICAgICBhWzNdICsgJywgJyArIGFbNF0gKyAnLCAnICsgYVs1XSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0MmQuZnJvYiA9IGZ1bmN0aW9uIChhKSB7IFxuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgMSkpXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MmQgPSBtYXQyZDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIDN4MyBNYXRyaXhcbiAqIEBuYW1lIG1hdDNcbiAqL1xuXG52YXIgbWF0MyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0M1xuICpcbiAqIEByZXR1cm5zIHttYXQzfSBhIG5ldyAzeDMgbWF0cml4XG4gKi9cbm1hdDMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDkpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMTtcbiAgICBvdXRbNV0gPSAwO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENvcGllcyB0aGUgdXBwZXItbGVmdCAzeDMgdmFsdWVzIGludG8gdGhlIGdpdmVuIG1hdDMuXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyAzeDMgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgICB0aGUgc291cmNlIDR4NCBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xubWF0My5mcm9tTWF0NCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbNF07XG4gICAgb3V0WzRdID0gYVs1XTtcbiAgICBvdXRbNV0gPSBhWzZdO1xuICAgIG91dFs2XSA9IGFbOF07XG4gICAgb3V0WzddID0gYVs5XTtcbiAgICBvdXRbOF0gPSBhWzEwXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IG1hdDMgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IGEgbWF0cml4IHRvIGNsb25lXG4gKiBAcmV0dXJucyB7bWF0M30gYSBuZXcgM3gzIG1hdHJpeFxuICovXG5tYXQzLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg5KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQzIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAxO1xuICAgIG91dFs1XSA9IDA7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNwb3NlIHRoZSB2YWx1ZXMgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnRyYW5zcG9zZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgICBpZiAob3V0ID09PSBhKSB7XG4gICAgICAgIHZhciBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMTIgPSBhWzVdO1xuICAgICAgICBvdXRbMV0gPSBhWzNdO1xuICAgICAgICBvdXRbMl0gPSBhWzZdO1xuICAgICAgICBvdXRbM10gPSBhMDE7XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGEwMjtcbiAgICAgICAgb3V0WzddID0gYTEyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFswXSA9IGFbMF07XG4gICAgICAgIG91dFsxXSA9IGFbM107XG4gICAgICAgIG91dFsyXSA9IGFbNl07XG4gICAgICAgIG91dFszXSA9IGFbMV07XG4gICAgICAgIG91dFs0XSA9IGFbNF07XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGFbMl07XG4gICAgICAgIG91dFs3XSA9IGFbNV07XG4gICAgICAgIG91dFs4XSA9IGFbOF07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmludmVydCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIGIwMSA9IGEyMiAqIGExMSAtIGExMiAqIGEyMSxcbiAgICAgICAgYjExID0gLWEyMiAqIGExMCArIGExMiAqIGEyMCxcbiAgICAgICAgYjIxID0gYTIxICogYTEwIC0gYTExICogYTIwLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYjAxICogZGV0O1xuICAgIG91dFsxXSA9ICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldDtcbiAgICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldDtcbiAgICBvdXRbM10gPSBiMTEgKiBkZXQ7XG4gICAgb3V0WzRdID0gKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0O1xuICAgIG91dFs2XSA9IGIyMSAqIGRldDtcbiAgICBvdXRbN10gPSAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQ7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIG91dFswXSA9IChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpO1xuICAgIG91dFsxXSA9IChhMDIgKiBhMjEgLSBhMDEgKiBhMjIpO1xuICAgIG91dFsyXSA9IChhMDEgKiBhMTIgLSBhMDIgKiBhMTEpO1xuICAgIG91dFszXSA9IChhMTIgKiBhMjAgLSBhMTAgKiBhMjIpO1xuICAgIG91dFs0XSA9IChhMDAgKiBhMjIgLSBhMDIgKiBhMjApO1xuICAgIG91dFs1XSA9IChhMDIgKiBhMTAgLSBhMDAgKiBhMTIpO1xuICAgIG91dFs2XSA9IChhMTAgKiBhMjEgLSBhMTEgKiBhMjApO1xuICAgIG91dFs3XSA9IChhMDEgKiBhMjAgLSBhMDAgKiBhMjEpO1xuICAgIG91dFs4XSA9IChhMDAgKiBhMTEgLSBhMDEgKiBhMTApO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQzLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIHJldHVybiBhMDAgKiAoYTIyICogYTExIC0gYTEyICogYTIxKSArIGEwMSAqICgtYTIyICogYTEwICsgYTEyICogYTIwKSArIGEwMiAqIChhMjEgKiBhMTAgLSBhMTEgKiBhMjApO1xufTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQzJ3NcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge21hdDN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMubXVsdGlwbHkgPSBmdW5jdGlvbiAob3V0LCBhLCBiKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG5cbiAgICAgICAgYjAwID0gYlswXSwgYjAxID0gYlsxXSwgYjAyID0gYlsyXSxcbiAgICAgICAgYjEwID0gYlszXSwgYjExID0gYls0XSwgYjEyID0gYls1XSxcbiAgICAgICAgYjIwID0gYls2XSwgYjIxID0gYls3XSwgYjIyID0gYls4XTtcblxuICAgIG91dFswXSA9IGIwMCAqIGEwMCArIGIwMSAqIGExMCArIGIwMiAqIGEyMDtcbiAgICBvdXRbMV0gPSBiMDAgKiBhMDEgKyBiMDEgKiBhMTEgKyBiMDIgKiBhMjE7XG4gICAgb3V0WzJdID0gYjAwICogYTAyICsgYjAxICogYTEyICsgYjAyICogYTIyO1xuXG4gICAgb3V0WzNdID0gYjEwICogYTAwICsgYjExICogYTEwICsgYjEyICogYTIwO1xuICAgIG91dFs0XSA9IGIxMCAqIGEwMSArIGIxMSAqIGExMSArIGIxMiAqIGEyMTtcbiAgICBvdXRbNV0gPSBiMTAgKiBhMDIgKyBiMTEgKiBhMTIgKyBiMTIgKiBhMjI7XG5cbiAgICBvdXRbNl0gPSBiMjAgKiBhMDAgKyBiMjEgKiBhMTAgKyBiMjIgKiBhMjA7XG4gICAgb3V0WzddID0gYjIwICogYTAxICsgYjIxICogYTExICsgYjIyICogYTIxO1xuICAgIG91dFs4XSA9IGIyMCAqIGEwMiArIGIyMSAqIGExMiArIGIyMiAqIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDMubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0My5tdWwgPSBtYXQzLm11bHRpcGx5O1xuXG4vKipcbiAqIFRyYW5zbGF0ZSBhIG1hdDMgYnkgdGhlIGdpdmVuIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDN9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMudHJhbnNsYXRlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG4gICAgICAgIHggPSB2WzBdLCB5ID0gdlsxXTtcblxuICAgIG91dFswXSA9IGEwMDtcbiAgICBvdXRbMV0gPSBhMDE7XG4gICAgb3V0WzJdID0gYTAyO1xuXG4gICAgb3V0WzNdID0gYTEwO1xuICAgIG91dFs0XSA9IGExMTtcbiAgICBvdXRbNV0gPSBhMTI7XG5cbiAgICBvdXRbNl0gPSB4ICogYTAwICsgeSAqIGExMCArIGEyMDtcbiAgICBvdXRbN10gPSB4ICogYTAxICsgeSAqIGExMSArIGEyMTtcbiAgICBvdXRbOF0gPSB4ICogYTAyICsgeSAqIGExMiArIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0MyBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKTtcblxuICAgIG91dFswXSA9IGMgKiBhMDAgKyBzICogYTEwO1xuICAgIG91dFsxXSA9IGMgKiBhMDEgKyBzICogYTExO1xuICAgIG91dFsyXSA9IGMgKiBhMDIgKyBzICogYTEyO1xuXG4gICAgb3V0WzNdID0gYyAqIGExMCAtIHMgKiBhMDA7XG4gICAgb3V0WzRdID0gYyAqIGExMSAtIHMgKiBhMDE7XG4gICAgb3V0WzVdID0gYyAqIGExMiAtIHMgKiBhMDI7XG5cbiAgICBvdXRbNl0gPSBhMjA7XG4gICAgb3V0WzddID0gYTIxO1xuICAgIG91dFs4XSA9IGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDMgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICoqL1xubWF0My5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV07XG5cbiAgICBvdXRbMF0gPSB4ICogYVswXTtcbiAgICBvdXRbMV0gPSB4ICogYVsxXTtcbiAgICBvdXRbMl0gPSB4ICogYVsyXTtcblxuICAgIG91dFszXSA9IHkgKiBhWzNdO1xuICAgIG91dFs0XSA9IHkgKiBhWzRdO1xuICAgIG91dFs1XSA9IHkgKiBhWzVdO1xuXG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29waWVzIHRoZSB2YWx1ZXMgZnJvbSBhIG1hdDJkIGludG8gYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byBjb3B5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKiovXG5tYXQzLmZyb21NYXQyZCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSAwO1xuXG4gICAgb3V0WzNdID0gYVsyXTtcbiAgICBvdXRbNF0gPSBhWzNdO1xuICAgIG91dFs1XSA9IDA7XG5cbiAgICBvdXRbNl0gPSBhWzRdO1xuICAgIG91dFs3XSA9IGFbNV07XG4gICAgb3V0WzhdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbWF0cml4IGZyb20gdGhlIGdpdmVuIHF1YXRlcm5pb25cbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge3F1YXR9IHEgUXVhdGVybmlvbiB0byBjcmVhdGUgbWF0cml4IGZyb21cbipcbiogQHJldHVybnMge21hdDN9IG91dFxuKi9cbm1hdDMuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbM10gPSB5eCAtIHd6O1xuICAgIG91dFs2XSA9IHp4ICsgd3k7XG5cbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFs0XSA9IDEgLSB4eCAtIHp6O1xuICAgIG91dFs3XSA9IHp5IC0gd3g7XG5cbiAgICBvdXRbMl0gPSB6eCAtIHd5O1xuICAgIG91dFs1XSA9IHp5ICsgd3g7XG4gICAgb3V0WzhdID0gMSAtIHh4IC0geXk7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbm9ybWFsIG1hdHJpeCAodHJhbnNwb3NlIGludmVyc2UpIGZyb20gdGhlIDR4NCBtYXRyaXhcbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge21hdDR9IGEgTWF0NCB0byBkZXJpdmUgdGhlIG5vcm1hbCBtYXRyaXggZnJvbVxuKlxuKiBAcmV0dXJucyB7bWF0M30gb3V0XG4qL1xubWF0My5ub3JtYWxGcm9tTWF0NCA9IGZ1bmN0aW9uIChvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XSxcblxuICAgICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXG4gICAgICAgIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMCxcbiAgICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxuICAgICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXG4gICAgICAgIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMSxcbiAgICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxuICAgICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXG4gICAgICAgIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMCxcbiAgICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxuICAgICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXG4gICAgICAgIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMSxcbiAgICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzFdID0gKGExMiAqIGIwOCAtIGExMCAqIGIxMSAtIGExMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzJdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG5cbiAgICBvdXRbM10gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcblxuICAgIG91dFs2XSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFs3XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG1hdCBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdtYXQzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVszXSArICcsICcgKyBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgXG4gICAgICAgICAgICAgICAgICAgIGFbNl0gKyAnLCAnICsgYVs3XSArICcsICcgKyBhWzhdICsgJyknO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIEZyb2Jlbml1cyBub3JtIG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0My5mcm9iID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4oTWF0aC5zcXJ0KE1hdGgucG93KGFbMF0sIDIpICsgTWF0aC5wb3coYVsxXSwgMikgKyBNYXRoLnBvdyhhWzJdLCAyKSArIE1hdGgucG93KGFbM10sIDIpICsgTWF0aC5wb3coYVs0XSwgMikgKyBNYXRoLnBvdyhhWzVdLCAyKSArIE1hdGgucG93KGFbNl0sIDIpICsgTWF0aC5wb3coYVs3XSwgMikgKyBNYXRoLnBvdyhhWzhdLCAyKSkpXG59O1xuXG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLm1hdDMgPSBtYXQzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNHg0IE1hdHJpeFxuICogQG5hbWUgbWF0NFxuICovXG5cbnZhciBtYXQ0ID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBpZGVudGl0eSBtYXQ0XG4gKlxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQ0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIG91dFs2XSA9IGFbNl07XG4gICAgb3V0WzddID0gYVs3XTtcbiAgICBvdXRbOF0gPSBhWzhdO1xuICAgIG91dFs5XSA9IGFbOV07XG4gICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgIG91dFsxMV0gPSBhWzExXTtcbiAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbNF0gPSBhWzRdO1xuICAgIG91dFs1XSA9IGFbNV07XG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQ0IHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgICAgICBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGEwMTtcbiAgICAgICAgb3V0WzZdID0gYVs5XTtcbiAgICAgICAgb3V0WzddID0gYVsxM107XG4gICAgICAgIG91dFs4XSA9IGEwMjtcbiAgICAgICAgb3V0WzldID0gYTEyO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhMDM7XG4gICAgICAgIG91dFsxM10gPSBhMTM7XG4gICAgICAgIG91dFsxNF0gPSBhMjM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGFbMV07XG4gICAgICAgIG91dFs1XSA9IGFbNV07XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhWzJdO1xuICAgICAgICBvdXRbOV0gPSBhWzZdO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbM107XG4gICAgICAgIG91dFsxM10gPSBhWzddO1xuICAgICAgICBvdXRbMTRdID0gYVsxMV07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV0sXG5cbiAgICAgICAgYjAwID0gYTAwICogYTExIC0gYTAxICogYTEwLFxuICAgICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXG4gICAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcbiAgICAgICAgYjAzID0gYTAxICogYTEyIC0gYTAyICogYTExLFxuICAgICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXG4gICAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcbiAgICAgICAgYjA2ID0gYTIwICogYTMxIC0gYTIxICogYTMwLFxuICAgICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXG4gICAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcbiAgICAgICAgYjA5ID0gYTIxICogYTMyIC0gYTIyICogYTMxLFxuICAgICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXG4gICAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMixcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcblxuICAgIGlmICghZGV0KSB7IFxuICAgICAgICByZXR1cm4gbnVsbDsgXG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcblxuICAgIG91dFswXSA9IChhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDkpICogZGV0O1xuICAgIG91dFsxXSA9IChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0O1xuICAgIG91dFsyXSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFszXSA9IChhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMpICogZGV0O1xuICAgIG91dFs0XSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICAgIG91dFs1XSA9IChhMDAgKiBiMTEgLSBhMDIgKiBiMDggKyBhMDMgKiBiMDcpICogZGV0O1xuICAgIG91dFs2XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs3XSA9IChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMTAgKiBiMTAgLSBhMTEgKiBiMDggKyBhMTMgKiBiMDYpICogZGV0O1xuICAgIG91dFs5XSA9IChhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYpICogZGV0O1xuICAgIG91dFsxMF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTFdID0gKGEyMSAqIGIwMiAtIGEyMCAqIGIwNCAtIGEyMyAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzEyXSA9IChhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYpICogZGV0O1xuICAgIG91dFsxM10gPSAoYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTRdID0gKGEzMSAqIGIwMSAtIGEzMCAqIGIwMyAtIGEzMiAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzE1XSA9IChhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XTtcblxuICAgIG91dFswXSAgPSAgKGExMSAqIChhMjIgKiBhMzMgLSBhMjMgKiBhMzIpIC0gYTIxICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgKyBhMzEgKiAoYTEyICogYTIzIC0gYTEzICogYTIyKSk7XG4gICAgb3V0WzFdICA9IC0oYTAxICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjEgKiAoYTAyICogYTMzIC0gYTAzICogYTMyKSArIGEzMSAqIChhMDIgKiBhMjMgLSBhMDMgKiBhMjIpKTtcbiAgICBvdXRbMl0gID0gIChhMDEgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSAtIGExMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGExMyAtIGEwMyAqIGExMikpO1xuICAgIG91dFszXSAgPSAtKGEwMSAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpIC0gYTExICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikgKyBhMjEgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzRdICA9IC0oYTEwICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjAgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSArIGEzMCAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpKTtcbiAgICBvdXRbNV0gID0gIChhMDAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMwICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikpO1xuICAgIG91dFs2XSAgPSAtKGEwMCAqIChhMTIgKiBhMzMgLSBhMTMgKiBhMzIpIC0gYTEwICogKGEwMiAqIGEzMyAtIGEwMyAqIGEzMikgKyBhMzAgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzddICA9ICAoYTAwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTAgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgICBvdXRbOF0gID0gIChhMTAgKiAoYTIxICogYTMzIC0gYTIzICogYTMxKSAtIGEyMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpICsgYTMwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSkpO1xuICAgIG91dFs5XSAgPSAtKGEwMCAqIChhMjEgKiBhMzMgLSBhMjMgKiBhMzEpIC0gYTIwICogKGEwMSAqIGEzMyAtIGEwMyAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTIzIC0gYTAzICogYTIxKSk7XG4gICAgb3V0WzEwXSA9ICAoYTAwICogKGExMSAqIGEzMyAtIGExMyAqIGEzMSkgLSBhMTAgKiAoYTAxICogYTMzIC0gYTAzICogYTMxKSArIGEzMCAqIChhMDEgKiBhMTMgLSBhMDMgKiBhMTEpKTtcbiAgICBvdXRbMTFdID0gLShhMDAgKiAoYTExICogYTIzIC0gYTEzICogYTIxKSAtIGExMCAqIChhMDEgKiBhMjMgLSBhMDMgKiBhMjEpICsgYTIwICogKGEwMSAqIGExMyAtIGEwMyAqIGExMSkpO1xuICAgIG91dFsxMl0gPSAtKGExMCAqIChhMjEgKiBhMzIgLSBhMjIgKiBhMzEpIC0gYTIwICogKGExMSAqIGEzMiAtIGExMiAqIGEzMSkgKyBhMzAgKiAoYTExICogYTIyIC0gYTEyICogYTIxKSk7XG4gICAgb3V0WzEzXSA9ICAoYTAwICogKGEyMSAqIGEzMiAtIGEyMiAqIGEzMSkgLSBhMjAgKiAoYTAxICogYTMyIC0gYTAyICogYTMxKSArIGEzMCAqIChhMDEgKiBhMjIgLSBhMDIgKiBhMjEpKTtcbiAgICBvdXRbMTRdID0gLShhMDAgKiAoYTExICogYTMyIC0gYTEyICogYTMxKSAtIGExMCAqIChhMDEgKiBhMzIgLSBhMDIgKiBhMzEpICsgYTMwICogKGEwMSAqIGExMiAtIGEwMiAqIGExMSkpO1xuICAgIG91dFsxNV0gPSAgKGEwMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpIC0gYTEwICogKGEwMSAqIGEyMiAtIGEwMiAqIGEyMSkgKyBhMjAgKiAoYTAxICogYTEyIC0gYTAyICogYTExKSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZGV0ZXJtaW5hbnQgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDQuZGV0ZXJtaW5hbnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgcmV0dXJuIGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0NCdzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0Lm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdO1xuXG4gICAgLy8gQ2FjaGUgb25seSB0aGUgY3VycmVudCBsaW5lIG9mIHRoZSBzZWNvbmQgbWF0cml4XG4gICAgdmFyIGIwICA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107ICBcbiAgICBvdXRbMF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzFdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsyXSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbM10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbNF07IGIxID0gYls1XTsgYjIgPSBiWzZdOyBiMyA9IGJbN107XG4gICAgb3V0WzRdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs1XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbNl0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzddID0gYjAqYTAzICsgYjEqYTEzICsgYjIqYTIzICsgYjMqYTMzO1xuXG4gICAgYjAgPSBiWzhdOyBiMSA9IGJbOV07IGIyID0gYlsxMF07IGIzID0gYlsxMV07XG4gICAgb3V0WzhdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs5XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTBdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxMV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbMTJdOyBiMSA9IGJbMTNdOyBiMiA9IGJbMTRdOyBiMyA9IGJbMTVdO1xuICAgIG91dFsxMl0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzEzXSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTRdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxNV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDQubXVsID0gbWF0NC5tdWx0aXBseTtcblxuLyoqXG4gKiBUcmFuc2xhdGUgYSBtYXQ0IGJ5IHRoZSBnaXZlbiB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdmVjdG9yIHRvIHRyYW5zbGF0ZSBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHYpIHtcbiAgICB2YXIgeCA9IHZbMF0sIHkgPSB2WzFdLCB6ID0gdlsyXSxcbiAgICAgICAgYTAwLCBhMDEsIGEwMiwgYTAzLFxuICAgICAgICBhMTAsIGExMSwgYTEyLCBhMTMsXG4gICAgICAgIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICAgIGlmIChhID09PSBvdXQpIHtcbiAgICAgICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzJdICogeCArIGFbNl0gKiB5ICsgYVsxMF0gKiB6ICsgYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICAgICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICAgICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFswXSA9IGEwMDsgb3V0WzFdID0gYTAxOyBvdXRbMl0gPSBhMDI7IG91dFszXSA9IGEwMztcbiAgICAgICAgb3V0WzRdID0gYTEwOyBvdXRbNV0gPSBhMTE7IG91dFs2XSA9IGExMjsgb3V0WzddID0gYTEzO1xuICAgICAgICBvdXRbOF0gPSBhMjA7IG91dFs5XSA9IGEyMTsgb3V0WzEwXSA9IGEyMjsgb3V0WzExXSA9IGEyMztcblxuICAgICAgICBvdXRbMTJdID0gYTAwICogeCArIGExMCAqIHkgKyBhMjAgKiB6ICsgYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhMDEgKiB4ICsgYTExICogeSArIGEyMSAqIHogKyBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYTAzICogeCArIGExMyAqIHkgKyBhMjMgKiB6ICsgYVsxNV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQ0IGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdGhlIHZlYzMgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICoqL1xubWF0NC5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV0sIHogPSB2WzJdO1xuXG4gICAgb3V0WzBdID0gYVswXSAqIHg7XG4gICAgb3V0WzFdID0gYVsxXSAqIHg7XG4gICAgb3V0WzJdID0gYVsyXSAqIHg7XG4gICAgb3V0WzNdID0gYVszXSAqIHg7XG4gICAgb3V0WzRdID0gYVs0XSAqIHk7XG4gICAgb3V0WzVdID0gYVs1XSAqIHk7XG4gICAgb3V0WzZdID0gYVs2XSAqIHk7XG4gICAgb3V0WzddID0gYVs3XSAqIHk7XG4gICAgb3V0WzhdID0gYVs4XSAqIHo7XG4gICAgb3V0WzldID0gYVs5XSAqIHo7XG4gICAgb3V0WzEwXSA9IGFbMTBdICogejtcbiAgICBvdXRbMTFdID0gYVsxMV0gKiB6O1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0NCBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGUgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQsIGF4aXMpIHtcbiAgICB2YXIgeCA9IGF4aXNbMF0sIHkgPSBheGlzWzFdLCB6ID0gYXhpc1syXSxcbiAgICAgICAgbGVuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiksXG4gICAgICAgIHMsIGMsIHQsXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjMsXG4gICAgICAgIGIwMCwgYjAxLCBiMDIsXG4gICAgICAgIGIxMCwgYjExLCBiMTIsXG4gICAgICAgIGIyMCwgYjIxLCBiMjI7XG5cbiAgICBpZiAoTWF0aC5hYnMobGVuKSA8IEdMTUFUX0VQU0lMT04pIHsgcmV0dXJuIG51bGw7IH1cbiAgICBcbiAgICBsZW4gPSAxIC8gbGVuO1xuICAgIHggKj0gbGVuO1xuICAgIHkgKj0gbGVuO1xuICAgIHogKj0gbGVuO1xuXG4gICAgcyA9IE1hdGguc2luKHJhZCk7XG4gICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgdCA9IDEgLSBjO1xuXG4gICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICBhMTAgPSBhWzRdOyBhMTEgPSBhWzVdOyBhMTIgPSBhWzZdOyBhMTMgPSBhWzddO1xuICAgIGEyMCA9IGFbOF07IGEyMSA9IGFbOV07IGEyMiA9IGFbMTBdOyBhMjMgPSBhWzExXTtcblxuICAgIC8vIENvbnN0cnVjdCB0aGUgZWxlbWVudHMgb2YgdGhlIHJvdGF0aW9uIG1hdHJpeFxuICAgIGIwMCA9IHggKiB4ICogdCArIGM7IGIwMSA9IHkgKiB4ICogdCArIHogKiBzOyBiMDIgPSB6ICogeCAqIHQgLSB5ICogcztcbiAgICBiMTAgPSB4ICogeSAqIHQgLSB6ICogczsgYjExID0geSAqIHkgKiB0ICsgYzsgYjEyID0geiAqIHkgKiB0ICsgeCAqIHM7XG4gICAgYjIwID0geCAqIHogKiB0ICsgeSAqIHM7IGIyMSA9IHkgKiB6ICogdCAtIHggKiBzOyBiMjIgPSB6ICogeiAqIHQgKyBjO1xuXG4gICAgLy8gUGVyZm9ybSByb3RhdGlvbi1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBiMDAgKyBhMTAgKiBiMDEgKyBhMjAgKiBiMDI7XG4gICAgb3V0WzFdID0gYTAxICogYjAwICsgYTExICogYjAxICsgYTIxICogYjAyO1xuICAgIG91dFsyXSA9IGEwMiAqIGIwMCArIGExMiAqIGIwMSArIGEyMiAqIGIwMjtcbiAgICBvdXRbM10gPSBhMDMgKiBiMDAgKyBhMTMgKiBiMDEgKyBhMjMgKiBiMDI7XG4gICAgb3V0WzRdID0gYTAwICogYjEwICsgYTEwICogYjExICsgYTIwICogYjEyO1xuICAgIG91dFs1XSA9IGEwMSAqIGIxMCArIGExMSAqIGIxMSArIGEyMSAqIGIxMjtcbiAgICBvdXRbNl0gPSBhMDIgKiBiMTAgKyBhMTIgKiBiMTEgKyBhMjIgKiBiMTI7XG4gICAgb3V0WzddID0gYTAzICogYjEwICsgYTEzICogYjExICsgYTIzICogYjEyO1xuICAgIG91dFs4XSA9IGEwMCAqIGIyMCArIGExMCAqIGIyMSArIGEyMCAqIGIyMjtcbiAgICBvdXRbOV0gPSBhMDEgKiBiMjAgKyBhMTEgKiBiMjEgKyBhMjEgKiBiMjI7XG4gICAgb3V0WzEwXSA9IGEwMiAqIGIyMCArIGExMiAqIGIyMSArIGEyMiAqIGIyMjtcbiAgICBvdXRbMTFdID0gYTAzICogYjIwICsgYTEzICogYjIxICsgYTIzICogYjIyO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGVYID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSxcbiAgICAgICAgYTIxID0gYVs5XSxcbiAgICAgICAgYTIyID0gYVsxMF0sXG4gICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgICAgIG91dFswXSAgPSBhWzBdO1xuICAgICAgICBvdXRbMV0gID0gYVsxXTtcbiAgICAgICAgb3V0WzJdICA9IGFbMl07XG4gICAgICAgIG91dFszXSAgPSBhWzNdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFs0XSA9IGExMCAqIGMgKyBhMjAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgKyBhMjIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgKyBhMjMgKiBzO1xuICAgIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICAgIG91dFs5XSA9IGEyMSAqIGMgLSBhMTEgKiBzO1xuICAgIG91dFsxMF0gPSBhMjIgKiBjIC0gYTEyICogcztcbiAgICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMjAgPSBhWzhdLFxuICAgICAgICBhMjEgPSBhWzldLFxuICAgICAgICBhMjIgPSBhWzEwXSxcbiAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIHJvd3NcbiAgICAgICAgb3V0WzRdICA9IGFbNF07XG4gICAgICAgIG91dFs1XSAgPSBhWzVdO1xuICAgICAgICBvdXRbNl0gID0gYVs2XTtcbiAgICAgICAgb3V0WzddICA9IGFbN107XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyAtIGEyMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyAtIGEyMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyAtIGEyMyAqIHM7XG4gICAgb3V0WzhdID0gYTAwICogcyArIGEyMCAqIGM7XG4gICAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gICAgb3V0WzEwXSA9IGEwMiAqIHMgKyBhMjIgKiBjO1xuICAgIG91dFsxMV0gPSBhMDMgKiBzICsgYTIzICogYztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQucm90YXRlWiA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGEwMCA9IGFbMF0sXG4gICAgICAgIGEwMSA9IGFbMV0sXG4gICAgICAgIGEwMiA9IGFbMl0sXG4gICAgICAgIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sXG4gICAgICAgIGExMSA9IGFbNV0sXG4gICAgICAgIGExMiA9IGFbNl0sXG4gICAgICAgIGExMyA9IGFbN107XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgICAgIG91dFs4XSAgPSBhWzhdO1xuICAgICAgICBvdXRbOV0gID0gYVs5XTtcbiAgICAgICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgICAgICBvdXRbMTFdID0gYVsxMV07XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyArIGExMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyArIGExMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyArIGExMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyArIGExMyAqIHM7XG4gICAgb3V0WzRdID0gYTEwICogYyAtIGEwMCAqIHM7XG4gICAgb3V0WzVdID0gYTExICogYyAtIGEwMSAqIHM7XG4gICAgb3V0WzZdID0gYTEyICogYyAtIGEwMiAqIHM7XG4gICAgb3V0WzddID0gYTEzICogYyAtIGEwMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiBhbmQgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIHZhciBxdWF0TWF0ID0gbWF0NC5jcmVhdGUoKTtcbiAqICAgICBxdWF0NC50b01hdDQocXVhdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5tdWx0aXBseShkZXN0LCBxdWF0TWF0KTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7dmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5mcm9tUm90YXRpb25UcmFuc2xhdGlvbiA9IGZ1bmN0aW9uIChvdXQsIHEsIHYpIHtcbiAgICAvLyBRdWF0ZXJuaW9uIG1hdGhcbiAgICB2YXIgeCA9IHFbMF0sIHkgPSBxWzFdLCB6ID0gcVsyXSwgdyA9IHFbM10sXG4gICAgICAgIHgyID0geCArIHgsXG4gICAgICAgIHkyID0geSArIHksXG4gICAgICAgIHoyID0geiArIHosXG5cbiAgICAgICAgeHggPSB4ICogeDIsXG4gICAgICAgIHh5ID0geCAqIHkyLFxuICAgICAgICB4eiA9IHggKiB6MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHl6ID0geSAqIHoyLFxuICAgICAgICB6eiA9IHogKiB6MixcbiAgICAgICAgd3ggPSB3ICogeDIsXG4gICAgICAgIHd5ID0gdyAqIHkyLFxuICAgICAgICB3eiA9IHcgKiB6MjtcblxuICAgIG91dFswXSA9IDEgLSAoeXkgKyB6eik7XG4gICAgb3V0WzFdID0geHkgKyB3ejtcbiAgICBvdXRbMl0gPSB4eiAtIHd5O1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0geHkgLSB3ejtcbiAgICBvdXRbNV0gPSAxIC0gKHh4ICsgenopO1xuICAgIG91dFs2XSA9IHl6ICsgd3g7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSB4eiArIHd5O1xuICAgIG91dFs5XSA9IHl6IC0gd3g7XG4gICAgb3V0WzEwXSA9IDEgLSAoeHggKyB5eSk7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IHZbMF07XG4gICAgb3V0WzEzXSA9IHZbMV07XG4gICAgb3V0WzE0XSA9IHZbMl07XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbm1hdDQuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFsyXSA9IHp4IC0gd3k7XG4gICAgb3V0WzNdID0gMDtcblxuICAgIG91dFs0XSA9IHl4IC0gd3o7XG4gICAgb3V0WzVdID0gMSAtIHh4IC0geno7XG4gICAgb3V0WzZdID0genkgKyB3eDtcbiAgICBvdXRbN10gPSAwO1xuXG4gICAgb3V0WzhdID0genggKyB3eTtcbiAgICBvdXRbOV0gPSB6eSAtIHd4O1xuICAgIG91dFsxMF0gPSAxIC0geHggLSB5eTtcbiAgICBvdXRbMTFdID0gMDtcblxuICAgIG91dFsxMl0gPSAwO1xuICAgIG91dFsxM10gPSAwO1xuICAgIG91dFsxNF0gPSAwO1xuICAgIG91dFsxNV0gPSAxO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgZnJ1c3R1bSBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtOdW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuZnJ1c3R1bSA9IGZ1bmN0aW9uIChvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIHJsID0gMSAvIChyaWdodCAtIGxlZnQpLFxuICAgICAgICB0YiA9IDEgLyAodG9wIC0gYm90dG9tKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IChuZWFyICogMikgKiBybDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IChuZWFyICogMikgKiB0YjtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gKHJpZ2h0ICsgbGVmdCkgKiBybDtcbiAgICBvdXRbOV0gPSAodG9wICsgYm90dG9tKSAqIHRiO1xuICAgIG91dFsxMF0gPSAoZmFyICsgbmVhcikgKiBuZjtcbiAgICBvdXRbMTFdID0gLTE7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IChmYXIgKiBuZWFyICogMikgKiBuZjtcbiAgICBvdXRbMTVdID0gMDtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge251bWJlcn0gZm92eSBWZXJ0aWNhbCBmaWVsZCBvZiB2aWV3IGluIHJhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhc3BlY3QgQXNwZWN0IHJhdGlvLiB0eXBpY2FsbHkgdmlld3BvcnQgd2lkdGgvaGVpZ2h0XG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnBlcnNwZWN0aXZlID0gZnVuY3Rpb24gKG91dCwgZm92eSwgYXNwZWN0LCBuZWFyLCBmYXIpIHtcbiAgICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IGYgLyBhc3BlY3Q7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSBmO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxMV0gPSAtMTtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gKDIgKiBmYXIgKiBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQub3J0aG8gPSBmdW5jdGlvbiAob3V0LCBsZWZ0LCByaWdodCwgYm90dG9tLCB0b3AsIG5lYXIsIGZhcikge1xuICAgIHZhciBsciA9IDEgLyAobGVmdCAtIHJpZ2h0KSxcbiAgICAgICAgYnQgPSAxIC8gKGJvdHRvbSAtIHRvcCksXG4gICAgICAgIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgICBvdXRbMF0gPSAtMiAqIGxyO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IDA7XG4gICAgb3V0WzVdID0gLTIgKiBidDtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gMDtcbiAgICBvdXRbOV0gPSAwO1xuICAgIG91dFsxMF0gPSAyICogbmY7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IChsZWZ0ICsgcmlnaHQpICogbHI7XG4gICAgb3V0WzEzXSA9ICh0b3AgKyBib3R0b20pICogYnQ7XG4gICAgb3V0WzE0XSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHt2ZWMzfSBleWUgUG9zaXRpb24gb2YgdGhlIHZpZXdlclxuICogQHBhcmFtIHt2ZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge3ZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5sb29rQXQgPSBmdW5jdGlvbiAob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgICB2YXIgeDAsIHgxLCB4MiwgeTAsIHkxLCB5MiwgejAsIHoxLCB6MiwgbGVuLFxuICAgICAgICBleWV4ID0gZXllWzBdLFxuICAgICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgICBleWV6ID0gZXllWzJdLFxuICAgICAgICB1cHggPSB1cFswXSxcbiAgICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICAgIHVweiA9IHVwWzJdLFxuICAgICAgICBjZW50ZXJ4ID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJ5ID0gY2VudGVyWzFdLFxuICAgICAgICBjZW50ZXJ6ID0gY2VudGVyWzJdO1xuXG4gICAgaWYgKE1hdGguYWJzKGV5ZXggLSBjZW50ZXJ4KSA8IEdMTUFUX0VQU0lMT04gJiZcbiAgICAgICAgTWF0aC5hYnMoZXlleSAtIGNlbnRlcnkpIDwgR0xNQVRfRVBTSUxPTiAmJlxuICAgICAgICBNYXRoLmFicyhleWV6IC0gY2VudGVyeikgPCBHTE1BVF9FUFNJTE9OKSB7XG4gICAgICAgIHJldHVybiBtYXQ0LmlkZW50aXR5KG91dCk7XG4gICAgfVxuXG4gICAgejAgPSBleWV4IC0gY2VudGVyeDtcbiAgICB6MSA9IGV5ZXkgLSBjZW50ZXJ5O1xuICAgIHoyID0gZXlleiAtIGNlbnRlcno7XG5cbiAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KHowICogejAgKyB6MSAqIHoxICsgejIgKiB6Mik7XG4gICAgejAgKj0gbGVuO1xuICAgIHoxICo9IGxlbjtcbiAgICB6MiAqPSBsZW47XG5cbiAgICB4MCA9IHVweSAqIHoyIC0gdXB6ICogejE7XG4gICAgeDEgPSB1cHogKiB6MCAtIHVweCAqIHoyO1xuICAgIHgyID0gdXB4ICogejEgLSB1cHkgKiB6MDtcbiAgICBsZW4gPSBNYXRoLnNxcnQoeDAgKiB4MCArIHgxICogeDEgKyB4MiAqIHgyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB4MCA9IDA7XG4gICAgICAgIHgxID0gMDtcbiAgICAgICAgeDIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHgwICo9IGxlbjtcbiAgICAgICAgeDEgKj0gbGVuO1xuICAgICAgICB4MiAqPSBsZW47XG4gICAgfVxuXG4gICAgeTAgPSB6MSAqIHgyIC0gejIgKiB4MTtcbiAgICB5MSA9IHoyICogeDAgLSB6MCAqIHgyO1xuICAgIHkyID0gejAgKiB4MSAtIHoxICogeDA7XG5cbiAgICBsZW4gPSBNYXRoLnNxcnQoeTAgKiB5MCArIHkxICogeTEgKyB5MiAqIHkyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB5MCA9IDA7XG4gICAgICAgIHkxID0gMDtcbiAgICAgICAgeTIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHkwICo9IGxlbjtcbiAgICAgICAgeTEgKj0gbGVuO1xuICAgICAgICB5MiAqPSBsZW47XG4gICAgfVxuXG4gICAgb3V0WzBdID0geDA7XG4gICAgb3V0WzFdID0geTA7XG4gICAgb3V0WzJdID0gejA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSB4MTtcbiAgICBvdXRbNV0gPSB5MTtcbiAgICBvdXRbNl0gPSB6MTtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IHgyO1xuICAgIG91dFs5XSA9IHkyO1xuICAgIG91dFsxMF0gPSB6MjtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gLSh4MCAqIGV5ZXggKyB4MSAqIGV5ZXkgKyB4MiAqIGV5ZXopO1xuICAgIG91dFsxM10gPSAtKHkwICogZXlleCArIHkxICogZXlleSArIHkyICogZXlleik7XG4gICAgb3V0WzE0XSA9IC0oejAgKiBleWV4ICsgejEgKiBleWV5ICsgejIgKiBleWV6KTtcbiAgICBvdXRbMTVdID0gMTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0NC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0NCgnICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgYVs2XSArICcsICcgKyBhWzddICsgJywgJyArXG4gICAgICAgICAgICAgICAgICAgIGFbOF0gKyAnLCAnICsgYVs5XSArICcsICcgKyBhWzEwXSArICcsICcgKyBhWzExXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVsxMl0gKyAnLCAnICsgYVsxM10gKyAnLCAnICsgYVsxNF0gKyAnLCAnICsgYVsxNV0gKyAnKSc7XG59O1xuXG4vKipcbiAqIFJldHVybnMgRnJvYmVuaXVzIG5vcm0gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gY2FsY3VsYXRlIEZyb2Jlbml1cyBub3JtIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBGcm9iZW5pdXMgbm9ybVxuICovXG5tYXQ0LmZyb2IgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgTWF0aC5wb3coYVs2XSwgMikgKyBNYXRoLnBvdyhhWzZdLCAyKSArIE1hdGgucG93KGFbN10sIDIpICsgTWF0aC5wb3coYVs4XSwgMikgKyBNYXRoLnBvdyhhWzldLCAyKSArIE1hdGgucG93KGFbMTBdLCAyKSArIE1hdGgucG93KGFbMTFdLCAyKSArIE1hdGgucG93KGFbMTJdLCAyKSArIE1hdGgucG93KGFbMTNdLCAyKSArIE1hdGgucG93KGFbMTRdLCAyKSArIE1hdGgucG93KGFbMTVdLCAyKSApKVxufTtcblxuXG5pZih0eXBlb2YoZXhwb3J0cykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZXhwb3J0cy5tYXQ0ID0gbWF0NDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIFF1YXRlcm5pb25cbiAqIEBuYW1lIHF1YXRcbiAqL1xuXG52YXIgcXVhdCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgcXVhdFxuICpcbiAqIEByZXR1cm5zIHtxdWF0fSBhIG5ldyBxdWF0ZXJuaW9uXG4gKi9cbnF1YXQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2V0cyBhIHF1YXRlcm5pb24gdG8gcmVwcmVzZW50IHRoZSBzaG9ydGVzdCByb3RhdGlvbiBmcm9tIG9uZVxuICogdmVjdG9yIHRvIGFub3RoZXIuXG4gKlxuICogQm90aCB2ZWN0b3JzIGFyZSBhc3N1bWVkIHRvIGJlIHVuaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgaW5pdGlhbCB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgZGVzdGluYXRpb24gdmVjdG9yXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQucm90YXRpb25UbyA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdG1wdmVjMyA9IHZlYzMuY3JlYXRlKCk7XG4gICAgdmFyIHhVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygxLDAsMCk7XG4gICAgdmFyIHlVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygwLDEsMCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgICAgIHZhciBkb3QgPSB2ZWMzLmRvdChhLCBiKTtcbiAgICAgICAgaWYgKGRvdCA8IC0wLjk5OTk5OSkge1xuICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB4VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgaWYgKHZlYzMubGVuZ3RoKHRtcHZlYzMpIDwgMC4wMDAwMDEpXG4gICAgICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB5VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgdmVjMy5ub3JtYWxpemUodG1wdmVjMywgdG1wdmVjMyk7XG4gICAgICAgICAgICBxdWF0LnNldEF4aXNBbmdsZShvdXQsIHRtcHZlYzMsIE1hdGguUEkpO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSBlbHNlIGlmIChkb3QgPiAwLjk5OTk5OSkge1xuICAgICAgICAgICAgb3V0WzBdID0gMDtcbiAgICAgICAgICAgIG91dFsxXSA9IDA7XG4gICAgICAgICAgICBvdXRbMl0gPSAwO1xuICAgICAgICAgICAgb3V0WzNdID0gMTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2ZWMzLmNyb3NzKHRtcHZlYzMsIGEsIGIpO1xuICAgICAgICAgICAgb3V0WzBdID0gdG1wdmVjM1swXTtcbiAgICAgICAgICAgIG91dFsxXSA9IHRtcHZlYzNbMV07XG4gICAgICAgICAgICBvdXRbMl0gPSB0bXB2ZWMzWzJdO1xuICAgICAgICAgICAgb3V0WzNdID0gMSArIGRvdDtcbiAgICAgICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBzcGVjaWZpZWQgcXVhdGVybmlvbiB3aXRoIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlblxuICogYXhlcy4gRWFjaCBheGlzIGlzIGEgdmVjMyBhbmQgaXMgZXhwZWN0ZWQgdG8gYmUgdW5pdCBsZW5ndGggYW5kXG4gKiBwZXJwZW5kaWN1bGFyIHRvIGFsbCBvdGhlciBzcGVjaWZpZWQgYXhlcy5cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZpZXcgIHRoZSB2ZWN0b3IgcmVwcmVzZW50aW5nIHRoZSB2aWV3aW5nIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSByaWdodCB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJyaWdodFwiIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSB1cCAgICB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJ1cFwiIGRpcmVjdGlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnNldEF4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hdHIgPSBtYXQzLmNyZWF0ZSgpO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgdmlldywgcmlnaHQsIHVwKSB7XG4gICAgICAgIG1hdHJbMF0gPSByaWdodFswXTtcbiAgICAgICAgbWF0clszXSA9IHJpZ2h0WzFdO1xuICAgICAgICBtYXRyWzZdID0gcmlnaHRbMl07XG5cbiAgICAgICAgbWF0clsxXSA9IHVwWzBdO1xuICAgICAgICBtYXRyWzRdID0gdXBbMV07XG4gICAgICAgIG1hdHJbN10gPSB1cFsyXTtcblxuICAgICAgICBtYXRyWzJdID0gLXZpZXdbMF07XG4gICAgICAgIG1hdHJbNV0gPSAtdmlld1sxXTtcbiAgICAgICAgbWF0cls4XSA9IC12aWV3WzJdO1xuXG4gICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIHF1YXQuZnJvbU1hdDMob3V0LCBtYXRyKSk7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBxdWF0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7cXVhdH0gYSBuZXcgcXVhdGVybmlvblxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY2xvbmUgPSB2ZWM0LmNsb25lO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3F1YXR9IGEgbmV3IHF1YXRlcm5pb25cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmZyb21WYWx1ZXMgPSB2ZWM0LmZyb21WYWx1ZXM7XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHF1YXQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBzb3VyY2UgcXVhdGVybmlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY29weSA9IHZlYzQuY29weTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSBxdWF0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB3IFcgY29tcG9uZW50XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zZXQgPSB2ZWM0LnNldDtcblxuLyoqXG4gKiBTZXQgYSBxdWF0IHRvIHRoZSBpZGVudGl0eSBxdWF0ZXJuaW9uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaWRlbnRpdHkgPSBmdW5jdGlvbihvdXQpIHtcbiAgICBvdXRbMF0gPSAwO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldHMgYSBxdWF0IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFuZCByb3RhdGlvbiBheGlzLFxuICogdGhlbiByZXR1cm5zIGl0LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIGFyb3VuZCB3aGljaCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqKi9cbnF1YXQuc2V0QXhpc0FuZ2xlID0gZnVuY3Rpb24ob3V0LCBheGlzLCByYWQpIHtcbiAgICByYWQgPSByYWQgKiAwLjU7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICAgIG91dFswXSA9IHMgKiBheGlzWzBdO1xuICAgIG91dFsxXSA9IHMgKiBheGlzWzFdO1xuICAgIG91dFsyXSA9IHMgKiBheGlzWzJdO1xuICAgIG91dFszXSA9IE1hdGguY29zKHJhZCk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmFkZCA9IHZlYzQuYWRkO1xuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICB2YXIgYXggPSBhWzBdLCBheSA9IGFbMV0sIGF6ID0gYVsyXSwgYXcgPSBhWzNdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdLCBidyA9IGJbM107XG5cbiAgICBvdXRbMF0gPSBheCAqIGJ3ICsgYXcgKiBieCArIGF5ICogYnogLSBheiAqIGJ5O1xuICAgIG91dFsxXSA9IGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieDtcbiAgICBvdXRbM10gPSBhdyAqIGJ3IC0gYXggKiBieCAtIGF5ICogYnkgLSBheiAqIGJ6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5tdWx0aXBseX1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0Lm11bCA9IHF1YXQubXVsdGlwbHk7XG5cbi8qKlxuICogU2NhbGVzIGEgcXVhdCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zY2FsZSA9IHZlYzQuc2NhbGU7XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVggPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ4ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYng7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF6ICogYng7XG4gICAgb3V0WzJdID0gYXogKiBidyAtIGF5ICogYng7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ5ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF3ICogYnk7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF4ICogYnk7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF5ICogYnk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBaIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVogPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ6ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF5ICogYno7XG4gICAgb3V0WzFdID0gYXkgKiBidyAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYno7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF6ICogYno7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgVyBjb21wb25lbnQgb2YgYSBxdWF0IGZyb20gdGhlIFgsIFksIGFuZCBaIGNvbXBvbmVudHMuXG4gKiBBc3N1bWVzIHRoYXQgcXVhdGVybmlvbiBpcyAxIHVuaXQgaW4gbGVuZ3RoLlxuICogQW55IGV4aXN0aW5nIFcgY29tcG9uZW50IHdpbGwgYmUgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBXIGNvbXBvbmVudCBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LmNhbGN1bGF0ZVcgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG5cbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSAtTWF0aC5zcXJ0KE1hdGguYWJzKDEuMCAtIHggKiB4IC0geSAqIHkgLSB6ICogeikpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byBxdWF0J3NcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmRvdCA9IHZlYzQuZG90O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlcnAgPSB2ZWM0LmxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuc2xlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgLy8gYmVuY2htYXJrczpcbiAgICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIGF4ID0gYVswXSwgYXkgPSBhWzFdLCBheiA9IGFbMl0sIGF3ID0gYVszXSxcbiAgICAgICAgYnggPSBiWzBdLCBieSA9IGJbMV0sIGJ6ID0gYlsyXSwgYncgPSBiWzNdO1xuXG4gICAgdmFyICAgICAgICBvbWVnYSwgY29zb20sIHNpbm9tLCBzY2FsZTAsIHNjYWxlMTtcblxuICAgIC8vIGNhbGMgY29zaW5lXG4gICAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3O1xuICAgIC8vIGFkanVzdCBzaWducyAoaWYgbmVjZXNzYXJ5KVxuICAgIGlmICggY29zb20gPCAwLjAgKSB7XG4gICAgICAgIGNvc29tID0gLWNvc29tO1xuICAgICAgICBieCA9IC0gYng7XG4gICAgICAgIGJ5ID0gLSBieTtcbiAgICAgICAgYnogPSAtIGJ6O1xuICAgICAgICBidyA9IC0gYnc7XG4gICAgfVxuICAgIC8vIGNhbGN1bGF0ZSBjb2VmZmljaWVudHNcbiAgICBpZiAoICgxLjAgLSBjb3NvbSkgPiAwLjAwMDAwMSApIHtcbiAgICAgICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgICAgIG9tZWdhICA9IE1hdGguYWNvcyhjb3NvbSk7XG4gICAgICAgIHNpbm9tICA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgc2NhbGUwID0gTWF0aC5zaW4oKDEuMCAtIHQpICogb21lZ2EpIC8gc2lub207XG4gICAgICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbTtcbiAgICB9IGVsc2UgeyAgICAgICAgXG4gICAgICAgIC8vIFwiZnJvbVwiIGFuZCBcInRvXCIgcXVhdGVybmlvbnMgYXJlIHZlcnkgY2xvc2UgXG4gICAgICAgIC8vICAuLi4gc28gd2UgY2FuIGRvIGEgbGluZWFyIGludGVycG9sYXRpb25cbiAgICAgICAgc2NhbGUwID0gMS4wIC0gdDtcbiAgICAgICAgc2NhbGUxID0gdDtcbiAgICB9XG4gICAgLy8gY2FsY3VsYXRlIGZpbmFsIHZhbHVlc1xuICAgIG91dFswXSA9IHNjYWxlMCAqIGF4ICsgc2NhbGUxICogYng7XG4gICAgb3V0WzFdID0gc2NhbGUwICogYXkgKyBzY2FsZTEgKiBieTtcbiAgICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6O1xuICAgIG91dFszXSA9IHNjYWxlMCAqIGF3ICsgc2NhbGUxICogYnc7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgaW52ZXJzZSBvZiBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBpbnZlcnNlIG9mXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgZG90ID0gYTAqYTAgKyBhMSphMSArIGEyKmEyICsgYTMqYTMsXG4gICAgICAgIGludkRvdCA9IGRvdCA/IDEuMC9kb3QgOiAwO1xuICAgIFxuICAgIC8vIFRPRE86IFdvdWxkIGJlIGZhc3RlciB0byByZXR1cm4gWzAsMCwwLDBdIGltbWVkaWF0ZWx5IGlmIGRvdCA9PSAwXG5cbiAgICBvdXRbMF0gPSAtYTAqaW52RG90O1xuICAgIG91dFsxXSA9IC1hMSppbnZEb3Q7XG4gICAgb3V0WzJdID0gLWEyKmludkRvdDtcbiAgICBvdXRbM10gPSBhMyppbnZEb3Q7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY29uanVnYXRlIG9mIGEgcXVhdFxuICogSWYgdGhlIHF1YXRlcm5pb24gaXMgbm9ybWFsaXplZCwgdGhpcyBmdW5jdGlvbiBpcyBmYXN0ZXIgdGhhbiBxdWF0LmludmVyc2UgYW5kIHByb2R1Y2VzIHRoZSBzYW1lIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBjb25qdWdhdGUgb2ZcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xucXVhdC5jb25qdWdhdGUgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF07XG4gICAgb3V0WzFdID0gLWFbMV07XG4gICAgb3V0WzJdID0gLWFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubGVuZ3RoID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBxdWF0Lmxlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlbiA9IHF1YXQubGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zcXVhcmVkTGVuZ3RoID0gdmVjNC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5zcXVhcmVkTGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuc3FyTGVuID0gcXVhdC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubm9ybWFsaXplID0gdmVjNC5ub3JtYWxpemU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHF1YXRlcm5pb24gZnJvbSB0aGUgZ2l2ZW4gM3gzIHJvdGF0aW9uIG1hdHJpeC5cbiAqXG4gKiBOT1RFOiBUaGUgcmVzdWx0YW50IHF1YXRlcm5pb24gaXMgbm90IG5vcm1hbGl6ZWQsIHNvIHlvdSBzaG91bGQgYmUgc3VyZVxuICogdG8gcmVub3JtYWxpemUgdGhlIHF1YXRlcm5pb24geW91cnNlbGYgd2hlcmUgbmVjZXNzYXJ5LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHttYXQzfSBtIHJvdGF0aW9uIG1hdHJpeFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuZnJvbU1hdDMgPSBmdW5jdGlvbihvdXQsIG0pIHtcbiAgICAvLyBBbGdvcml0aG0gaW4gS2VuIFNob2VtYWtlJ3MgYXJ0aWNsZSBpbiAxOTg3IFNJR0dSQVBIIGNvdXJzZSBub3Rlc1xuICAgIC8vIGFydGljbGUgXCJRdWF0ZXJuaW9uIENhbGN1bHVzIGFuZCBGYXN0IEFuaW1hdGlvblwiLlxuICAgIHZhciBmVHJhY2UgPSBtWzBdICsgbVs0XSArIG1bOF07XG4gICAgdmFyIGZSb290O1xuXG4gICAgaWYgKCBmVHJhY2UgPiAwLjAgKSB7XG4gICAgICAgIC8vIHx3fCA+IDEvMiwgbWF5IGFzIHdlbGwgY2hvb3NlIHcgPiAxLzJcbiAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMS4wKTsgIC8vIDJ3XG4gICAgICAgIG91dFszXSA9IDAuNSAqIGZSb290O1xuICAgICAgICBmUm9vdCA9IDAuNS9mUm9vdDsgIC8vIDEvKDR3KVxuICAgICAgICBvdXRbMF0gPSAobVs3XS1tWzVdKSpmUm9vdDtcbiAgICAgICAgb3V0WzFdID0gKG1bMl0tbVs2XSkqZlJvb3Q7XG4gICAgICAgIG91dFsyXSA9IChtWzNdLW1bMV0pKmZSb290O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHx3fCA8PSAxLzJcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBpZiAoIG1bNF0gPiBtWzBdIClcbiAgICAgICAgICBpID0gMTtcbiAgICAgICAgaWYgKCBtWzhdID4gbVtpKjMraV0gKVxuICAgICAgICAgIGkgPSAyO1xuICAgICAgICB2YXIgaiA9IChpKzEpJTM7XG4gICAgICAgIHZhciBrID0gKGkrMiklMztcbiAgICAgICAgXG4gICAgICAgIGZSb290ID0gTWF0aC5zcXJ0KG1baSozK2ldLW1baiozK2pdLW1bayozK2tdICsgMS4wKTtcbiAgICAgICAgb3V0W2ldID0gMC41ICogZlJvb3Q7XG4gICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7XG4gICAgICAgIG91dFszXSA9IChtW2sqMytqXSAtIG1baiozK2tdKSAqIGZSb290O1xuICAgICAgICBvdXRbal0gPSAobVtqKjMraV0gKyBtW2kqMytqXSkgKiBmUm9vdDtcbiAgICAgICAgb3V0W2tdID0gKG1bayozK2ldICsgbVtpKjMra10pICogZlJvb3Q7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBxdWF0ZW5pb25cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG5xdWF0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdxdWF0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMucXVhdCA9IHF1YXQ7XG59XG47XG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbiAgfSkoc2hpbS5leHBvcnRzKTtcbn0pKHRoaXMpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBjb25zdGFudCh2YWx1ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVOdW1iZXIoYSwgYiwgdCkge1xuICAgIHJldHVybiAoYSAqICgxIC0gdCkpICsgKGIgKiB0KTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVBcnJheShhLCBiLCB0KSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBpbnRlcnBvbGF0ZU51bWJlcihhW2ldLCBiW2ldLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0c1snaW50ZXJwb2xhdGVkJ10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzLFxuICAgICAgICBiYXNlID0gZi5iYXNlIHx8IDEsXG4gICAgICAgIGludGVycG9sYXRlID0gQXJyYXkuaXNBcnJheShzdG9wc1swXVsxXSkgPyBpbnRlcnBvbGF0ZUFycmF5IDogaW50ZXJwb2xhdGVOdW1iZXI7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oeikge1xuICAgICAgICAvLyBmaW5kIHRoZSB0d28gc3RvcHMgd2hpY2ggdGhlIGN1cnJlbnQgeiBpcyBiZXR3ZWVuXG4gICAgICAgIHZhciBsb3csIGhpZ2g7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0b3AgPSBzdG9wc1tpXTtcblxuICAgICAgICAgICAgaWYgKHN0b3BbMF0gPD0geikge1xuICAgICAgICAgICAgICAgIGxvdyA9IHN0b3A7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdG9wWzBdID4geikge1xuICAgICAgICAgICAgICAgIGhpZ2ggPSBzdG9wO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxvdyAmJiBoaWdoKSB7XG4gICAgICAgICAgICB2YXIgem9vbURpZmYgPSBoaWdoWzBdIC0gbG93WzBdLFxuICAgICAgICAgICAgICAgIHpvb21Qcm9ncmVzcyA9IHogLSBsb3dbMF0sXG5cbiAgICAgICAgICAgICAgICB0ID0gYmFzZSA9PT0gMSA/XG4gICAgICAgICAgICAgICAgem9vbVByb2dyZXNzIC8gem9vbURpZmYgOlxuICAgICAgICAgICAgICAgIChNYXRoLnBvdyhiYXNlLCB6b29tUHJvZ3Jlc3MpIC0gMSkgLyAoTWF0aC5wb3coYmFzZSwgem9vbURpZmYpIC0gMSk7XG5cbiAgICAgICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZShsb3dbMV0sIGhpZ2hbMV0sIHQpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobG93KSB7XG4gICAgICAgICAgICByZXR1cm4gbG93WzFdO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoaGlnaCkge1xuICAgICAgICAgICAgcmV0dXJuIGhpZ2hbMV07XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuZXhwb3J0c1sncGllY2V3aXNlLWNvbnN0YW50J10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHopIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHN0b3BzW2ldWzBdID4geikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9wc1tpID09PSAwID8gMCA6IGkgLSAxXVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdG9wc1tzdG9wcy5sZW5ndGggLSAxXVsxXTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi4vLi4vcmVmZXJlbmNlL2xhdGVzdC5qcycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9wYXJzZWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHlsZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZShzdHlsZSwgcmVmZXJlbmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xudmFyIGZvcm1hdCA9IHJlcXVpcmUoJ3V0aWwnKS5mb3JtYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3R5bGUsIHJlZmVyZW5jZSkge1xuXG4gICAgdmFyIGNvbnN0YW50cyA9IHN0eWxlLmNvbnN0YW50cyB8fCB7fSxcbiAgICAgICAgbGF5ZXJzID0ge30sXG4gICAgICAgIGVycm9ycyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZXJyb3Ioa2V5LCB2YWwgLyosIG1lc3NhZ2UsIC4uLiovKSB7XG4gICAgICAgIHZhciBlcnIgPSB7XG4gICAgICAgICAgICBtZXNzYWdlOiAoa2V5ID8ga2V5ICsgJzogJyA6ICcnKSArXG4gICAgICAgICAgICBmb3JtYXQuYXBwbHkoZm9ybWF0LCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsLl9fbGluZV9fKSB7XG4gICAgICAgICAgICBlcnIubGluZSA9IHZhbC5fX2xpbmVfXztcbiAgICAgICAgfVxuXG4gICAgICAgIGVycm9ycy5wdXNoKGVycik7XG4gICAgfVxuXG4gICAgLy8gTWFpbiByZWN1cnNpdmUgdmFsaWRhdGlvbiBmdW5jdGlvbi4gVHJhY2tzOlxuICAgIC8vXG4gICAgLy8gLSBrZXk6IHN0cmluZyByZXByZXNlbnRpbmcgbG9jYXRpb24gb2YgdmFsaWRhdGlvbiBpbiBzdHlsZSB0cmVlLiBVc2VkIG9ubHlcbiAgICAvLyAgIGZvciBtb3JlIGluZm9ybWF0aXZlIGVycm9yIHJlcG9ydGluZy5cbiAgICAvLyAtIHZhbDogY3VycmVudCB2YWx1ZSBmcm9tIHN0eWxlIGJlaW5nIGV2YWx1YXRlZC4gTWF5IGJlIGFueXRoaW5nIGZyb20gYVxuICAgIC8vICAgaGlnaCBsZXZlbCBvYmplY3QgdGhhdCBuZWVkcyB0byBiZSBkZXNjZW5kZWQgaW50byBkZWVwZXIgb3IgYSBzaW1wbGVcbiAgICAvLyAgIHNjYWxhciB2YWx1ZS5cbiAgICAvLyAtIHNwZWM6IGN1cnJlbnQgc3BlYyBiZWluZyBldmFsdWF0ZWQuIFRyYWNrcyB2YWwuXG4gICAgLy9cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcblxuICAgICAgICAvLyBDb25zdGFudHNcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIHZhbFswXSA9PT0gJ0AnKSB7XG4gICAgICAgICAgICBpZiAoISh2YWwgaW4gY29uc3RhbnRzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2NvbnN0YW50IFwiJXNcIiBub3QgZm91bmQnLCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsID0gY29uc3RhbnRzW3ZhbF07XG4gICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRnVuY3Rpb25zXG4gICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uICYmIHR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRhdGUuZnVuY3Rpb24oa2V5LCB2YWwsIHNwZWMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNwZWMudHlwZSkge1xuICAgICAgICAgICAgdmFyIHZhbGlkYXRvciA9IHZhbGlkYXRlW3NwZWMudHlwZV07XG4gICAgICAgICAgICBpZiAodmFsaWRhdG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbGlkYXRvcihrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzcGVjID0gcmVmZXJlbmNlW3NwZWMudHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHNwZWMpO1xuICAgIH1cblxuICAgIHZhbGlkYXRlLmNvbnN0YW50cyA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICBpZiAodHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ29iamVjdCBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGsgaW4gdmFsKSB7XG4gICAgICAgICAgICBpZiAoa1swXSAhPT0gJ0AnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJy4nICsgaywgdmFsW2tdLCAnY29uc3RhbnRzIG11c3Qgc3RhcnQgd2l0aCBcIkBcIicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLnNvdXJjZSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnXCJ0eXBlXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgICAgICBjYXNlICdyYXN0ZXInOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV90aWxlKTtcblxuICAgICAgICAgICAgICAgIGlmICgndXJsJyBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChbJ3R5cGUnLCAndXJsJywgJ3RpbGVTaXplJ10uaW5kZXhPZihwcm9wKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXkgKyAnLicgKyBwcm9wLCB2YWxbcHJvcF0sICdhIHNvdXJjZSB3aXRoIGEgXCJ1cmxcIiBwcm9wZXJ0eSBtYXkgbm90IGluY2x1ZGUgYSBcIiVzXCIgcHJvcGVydHknLCBwcm9wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZ2VvanNvbic6XG4gICAgICAgICAgICAgICAgdmFsaWRhdGUub2JqZWN0KGtleSwgdmFsLCByZWZlcmVuY2Uuc291cmNlX2dlb2pzb24pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndmlkZW8nOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV92aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJy50eXBlJywgdmFsLnR5cGUsIHt2YWx1ZXM6IFsndmVjdG9yJywgJ3Jhc3RlcicsICdnZW9qc29uJywgJ3ZpZGVvJ119KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YWxpZGF0ZS5sYXllciA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUgJiYgIXZhbC5yZWYpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnZWl0aGVyIFwidHlwZVwiIG9yIFwicmVmXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpLFxuICAgICAgICAgICAgcmVmID0gdW5idW5kbGUodmFsLnJlZik7XG5cbiAgICAgICAgaWYgKHZhbC5pZCkge1xuICAgICAgICAgICAgaWYgKGxheWVyc1t2YWwuaWRdKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwuaWQsICdkdXBsaWNhdGUgbGF5ZXIgaWQgXCIlc1wiLCBwcmV2aW91c2x5IHVzZWQgYXQgbGluZSAlZCcsIHZhbC5pZCwgbGF5ZXJzW3ZhbC5pZF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsYXllcnNbdmFsLmlkXSA9IHZhbC5pZC5fX2xpbmVfXztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgncmVmJyBpbiB2YWwpIHtcbiAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJywgJ2ZpbHRlcicsICdsYXlvdXQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHAgaW4gdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsW3BdLCAnXCIlc1wiIGlzIHByb2hpYml0ZWQgZm9yIHJlZiBsYXllcnMnLCBwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHBhcmVudDtcblxuICAgICAgICAgICAgc3R5bGUubGF5ZXJzLmZvckVhY2goZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAobGF5ZXIuaWQgPT0gcmVmKSBwYXJlbnQgPSBsYXllcjtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBsYXllciBcIiVzXCIgbm90IGZvdW5kJywgcmVmKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50LnJlZikge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBjYW5ub3QgcmVmZXJlbmNlIGFub3RoZXIgcmVmIGxheWVyJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJlbnQudHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlICE9PSAnYmFja2dyb3VuZCcpIHtcbiAgICAgICAgICAgIGlmICghdmFsLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcInNvdXJjZVwiJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzb3VyY2UgPSBzdHlsZS5zb3VyY2VzW3ZhbC5zb3VyY2VdO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ3NvdXJjZSBcIiVzXCIgbm90IGZvdW5kJywgdmFsLnNvdXJjZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzb3VyY2UudHlwZSA9PSAndmVjdG9yJyAmJiB0eXBlID09ICdyYXN0ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ2xheWVyIFwiJXNcIiByZXF1aXJlcyBhIHJhc3RlciBzb3VyY2UnLCB2YWwuaWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc291cmNlLnR5cGUgPT0gJ3Jhc3RlcicgJiYgdHlwZSAhPSAncmFzdGVyJykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbC5zb3VyY2UsICdsYXllciBcIiVzXCIgcmVxdWlyZXMgYSB2ZWN0b3Igc291cmNlJywgdmFsLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5sYXllciwge1xuICAgICAgICAgICAgZmlsdGVyOiB2YWxpZGF0ZS5maWx0ZXIsXG4gICAgICAgICAgICBsYXlvdXQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ2xheW91dF8nICsgdHlwZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGUgJiYgc3BlYyAmJiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFpbnQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ3BhaW50XycgKyB0eXBlXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZSAmJiBzcGVjICYmIHZhbGlkYXRlKGtleSwgdmFsLCBzcGVjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLm9iamVjdCA9IGZ1bmN0aW9uIChrZXksIHZhbCwgc3BlYywgdmFsaWRhdG9ycykge1xuICAgICAgICB2YWxpZGF0b3JzID0gdmFsaWRhdG9ycyB8fCB7fTtcblxuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdvYmplY3QgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBrIGluIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNwZWNrZXkgPSBrLnNwbGl0KCcuJylbMF07IC8vIHRyZWF0ICdwYWludC4qJyBhcyAncGFpbnQnXG4gICAgICAgICAgICB2YXIgZGVmID0gc3BlY1tzcGVja2V5XSB8fCBzcGVjWycqJ107XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHNwZWNrZXkubWF0Y2goL14oLiopLXRyYW5zaXRpb24kLyk7XG5cbiAgICAgICAgICAgIGlmIChkZWYpIHtcbiAgICAgICAgICAgICAgICAodmFsaWRhdG9yc1tzcGVja2V5XSB8fCB2YWxpZGF0ZSkoKGtleSA/IGtleSArICcuJyA6IGtleSkgKyBrLCB2YWxba10sIGRlZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zaXRpb24gJiYgc3BlY1t0cmFuc2l0aW9uWzFdXSAmJiBzcGVjW3RyYW5zaXRpb25bMV1dLnRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZSgoa2V5ID8ga2V5ICsgJy4nIDoga2V5KSArIGssIHZhbFtrXSwgcmVmZXJlbmNlLnRyYW5zaXRpb24pO1xuICAgICAgICAgICAgLy8gdG9sZXJhdGUgcm9vdC1sZXZlbCBleHRyYSBrZXlzICYgYXJiaXRyYXJ5IGxheWVyIHByb3BlcnRpZXNcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ICE9PSAnJyAmJiBrZXkuc3BsaXQoJy4nKS5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbFtrXSwgJ3Vua25vd24gcHJvcGVydHkgXCIlc1wiJywgayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBsIGluIHNwZWMpIHtcbiAgICAgICAgICAgIGlmIChzcGVjW2xdLnJlcXVpcmVkICYmIHNwZWNbbF1bJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIHZhbFtsXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwiJXNcIicsIGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmFycmF5ID0gZnVuY3Rpb24gKGtleSwgdmFsLCBzcGVjLCB2YWxpZGF0b3IpIHtcbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzcGVjLmxlbmd0aCAmJiB2YWwubGVuZ3RoICE9PSBzcGVjLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgbGVuZ3RoICVkIGV4cGVjdGVkLCBsZW5ndGggJWQgZm91bmQnLCBzcGVjLmxlbmd0aCwgdmFsLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdmFsdWUgPSB7XG4gICAgICAgICAgICBcInR5cGVcIjogc3BlYy52YWx1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzdHlsZS52ZXJzaW9uIDwgNykge1xuICAgICAgICAgICAgdmFsdWUuZnVuY3Rpb24gPSBzcGVjLmZ1bmN0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZl8oc3BlYy52YWx1ZSkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHNwZWMudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgKHZhbGlkYXRvciB8fCB2YWxpZGF0ZSkoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZmlsdGVyID0gZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICAgICAgdmFyIHR5cGU7XG5cbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwubGVuZ3RoIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnZmlsdGVyIGFycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCAxIGVsZW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1swXScsIHZhbFswXSwgcmVmZXJlbmNlLmZpbHRlcl9vcGVyYXRvcik7XG5cbiAgICAgICAgc3dpdGNoICh1bmJ1bmRsZSh2YWxbMF0pKSB7XG4gICAgICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID49IDIgJiYgdmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdcIiR0eXBlXCIgY2Fubm90IGJlIHVzZSB3aXRoIG9wZXJhdG9yIFwiJXNcIicsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnPT0nOlxuICAgICAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoICE9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdmaWx0ZXIgYXJyYXkgZm9yIG9wZXJhdG9yIFwiJXNcIiBtdXN0IGhhdmUgMyBlbGVtZW50cycsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnaW4nOlxuICAgICAgICAgICAgY2FzZSAnIWluJzpcbiAgICAgICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSB0eXBlb2ZfKHZhbFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ3N0cmluZyBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWxbMV1bMF0gPT09ICdAJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ2ZpbHRlciBrZXkgY2Fubm90IGJlIGEgY29uc3RhbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWxbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCByZWZlcmVuY2UuZ2VvbWV0cnlfdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgdmFsW2ldWzBdID09PSAnQCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbJyArIGkgKyAnXScsIHZhbFtpXSwgJ2ZpbHRlciB2YWx1ZSBjYW5ub3QgYmUgYSBjb25zdGFudCcpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgIT09ICdzdHJpbmcnICYmIHR5cGUgIT09ICdudW1iZXInICYmIHR5cGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCAnc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4gZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2FueSc6XG4gICAgICAgICAgICBjYXNlICdhbGwnOlxuICAgICAgICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZS5maWx0ZXIoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZnVuY3Rpb24gPSBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5mdW5jdGlvbiwge1xuICAgICAgICAgICAgc3RvcHM6IGZ1bmN0aW9uIChrZXksIHZhbCwgYXJyYXlTcGVjKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RTdG9wID0gLUluZmluaXR5O1xuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmFycmF5KGtleSwgdmFsLCBhcnJheVNwZWMsIGZ1bmN0aW9uIHZhbGlkYXRlU3RvcChrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mXyh2YWwpICE9PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdhcnJheSBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlb2ZfKHZhbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2FycmF5IGxlbmd0aCAlZCBleHBlY3RlZCwgbGVuZ3RoICVkIGZvdW5kJywgMiwgdmFsLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZShrZXkgKyAnWzBdJywgdmFsWzBdLCB7dHlwZTogJ251bWJlcid9KTtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGUoa2V5ICsgJ1sxXScsIHZhbFsxXSwgc3BlYyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZl8odmFsWzBdKSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uID09PSAncGllY2V3aXNlLWNvbnN0YW50JyAmJiB2YWxbMF0gJSAxICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1swXScsIHZhbFswXSwgJ3pvb20gbGV2ZWwgZm9yIHBpZWNld2lzZS1jb25zdGFudCBmdW5jdGlvbnMgbXVzdCBiZSBhbiBpbnRlZ2VyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxbMF0gPCBsYXN0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbMF0nLCB2YWxbMF0sICdhcnJheSBzdG9wcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFN0b3AgPSB2YWxbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2ZfKHZhbCkgPT09ICdhcnJheScgJiYgdmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2FycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgc3RvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmVudW0gPSBmdW5jdGlvbiAoa2V5LCB2YWwsIHNwZWMpIHtcbiAgICAgICAgaWYgKHNwZWMudmFsdWVzLmluZGV4T2YodW5idW5kbGUodmFsKSkgPT09IC0xKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2V4cGVjdGVkIG9uZSBvZiBbJXNdLCAlcyBmb3VuZCcsIHNwZWMudmFsdWVzLmpvaW4oJywgJyksIHZhbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuY29sb3IgPSBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2NvbG9yIGV4cGVjdGVkLCAlcyBmb3VuZCcsIHR5cGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcnNlQ1NTQ29sb3IodmFsKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdjb2xvciBleHBlY3RlZCwgXCIlc1wiIGZvdW5kJywgdmFsKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB0eXBlVmFsaWRhdG9yKGV4cGVjdGVkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICAgICAgdmFyIGFjdHVhbCA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgICAgIGlmIChhY3R1YWwgIT09IGV4cGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBleHBlY3RlZCwgJXMgZm91bmQnLCBleHBlY3RlZCwgYWN0dWFsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCdtaW5pbXVtJyBpbiBzcGVjICYmIHZhbCA8IHNwZWMubWluaW11bSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnJXMgaXMgbGVzcyB0aGFuIHRoZSBtaW5pbXVtIHZhbHVlICVzJywgdmFsLCBzcGVjLm1pbmltdW0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJ21heGltdW0nIGluIHNwZWMgJiYgdmFsID4gc3BlYy5tYXhpbXVtKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gdmFsdWUgJXMnLCB2YWwsIHNwZWMubWF4aW11bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFsaWRhdGUubnVtYmVyID0gdHlwZVZhbGlkYXRvcignbnVtYmVyJyk7XG4gICAgdmFsaWRhdGUuc3RyaW5nID0gdHlwZVZhbGlkYXRvcignc3RyaW5nJyk7XG4gICAgdmFsaWRhdGUuYm9vbGVhbiA9IHR5cGVWYWxpZGF0b3IoJ2Jvb2xlYW4nKTtcblxuICAgIHZhbGlkYXRlWycqJ10gPSBmdW5jdGlvbigpIHt9O1xuXG4gICAgdmFsaWRhdGUoJycsIHN0eWxlLCByZWZlcmVuY2UuJHJvb3QpO1xuXG4gICAgcmV0dXJuIGVycm9ycztcbn07XG5cbmZ1bmN0aW9uIHR5cGVvZl8odmFsKSB7XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE51bWJlcilcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBTdHJpbmcpXG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBpZiAodmFsIGluc3RhbmNlb2YgQm9vbGVhbilcbiAgICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICByZXR1cm4gJ2FycmF5JztcbiAgICBpZiAodmFsID09PSBudWxsKVxuICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgIHJldHVybiB0eXBlb2YgdmFsO1xufVxuXG5mdW5jdGlvbiB1bmJ1bmRsZShfKSB7XG4gICAgaWYgKF8gaW5zdGFuY2VvZiBOdW1iZXIgfHxcbiAgICAgICAgXyBpbnN0YW5jZW9mIFN0cmluZyB8fFxuICAgICAgICBfIGluc3RhbmNlb2YgQm9vbGVhbikge1xuICAgICAgICByZXR1cm4gXy52YWx1ZU9mKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIF87XG4gICAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3Y3Lmpzb24nKTtcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkdmVyc2lvblwiOiA3LFxuICBcIiRyb290XCI6IHtcbiAgICBcInZlcnNpb25cIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICA3XG4gICAgICBdLFxuICAgICAgXCJkb2NcIjogXCJTdHlsZXNoZWV0IHZlcnNpb24gbnVtYmVyLiBNdXN0IGJlIDcuXCJcbiAgICB9LFxuICAgIFwibmFtZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBodW1hbi1yZWFkYWJsZSBuYW1lIGZvciB0aGUgc3R5bGUuXCJcbiAgICB9LFxuICAgIFwiY29uc3RhbnRzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbnN0YW50c1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBvYmplY3Qgb2YgY29uc3RhbnRzIHRvIGJlIHJlZmVyZW5jZWQgaW4gbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZXNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwic291cmNlc1wiLFxuICAgICAgXCJkb2NcIjogXCJEYXRhIHNvdXJjZSBzcGVjaWZpY2F0aW9ucy5cIlxuICAgIH0sXG4gICAgXCJzcHJpdGVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgYmFzZSBVUkwgZm9yIHJldHJpZXZpbmcgdGhlIHNwcml0ZSBpbWFnZSBhbmQgbWV0YWRhdGEuIFRoZSBleHRlbnNpb25zIGAucG5nYCwgYC5qc29uYCBhbmQgc2NhbGUgZmFjdG9yIGBAMngucG5nYCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQuXCJcbiAgICB9LFxuICAgIFwiZ2x5cGhzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJBIFVSTCB0ZW1wbGF0ZSBmb3IgbG9hZGluZyBzaWduZWQtZGlzdGFuY2UtZmllbGQgZ2x5cGggc2V0cyBpbiBQQkYgZm9ybWF0LiBWYWxpZCB0b2tlbnMgYXJlIHtmb250c3RhY2t9IGFuZCB7cmFuZ2V9LlwiXG4gICAgfSxcbiAgICBcInRyYW5zaXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwidHJhbnNpdGlvblwiLFxuICAgICAgXCJkb2NcIjogXCJBIGdsb2JhbCB0cmFuc2l0aW9uIGRlZmluaXRpb24gdG8gdXNlIGFzIGEgZGVmYXVsdCBhY3Jvc3MgcHJvcGVydGllcy5cIlxuICAgIH0sXG4gICAgXCJsYXllcnNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJsYXllclwiLFxuICAgICAgXCJkb2NcIjogXCJMYXllcnMgd2lsbCBiZSBkcmF3biBpbiB0aGUgb3JkZXIgb2YgdGhpcyBhcnJheS5cIlxuICAgIH1cbiAgfSxcbiAgXCJjb25zdGFudHNcIjoge1xuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIkEgY29uc3RhbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkIHZlcmJhdGltIGluIHRoZSByZWZlcmVuY2luZyBwbGFjZS4gVGhpcyBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBvYmplY3RzIGFuZCBhcnJheXMuIEFsbCB2YXJpYWJsZSBuYW1lcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggYW4gYEBgIHN5bWJvbC5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VzXCI6IHtcbiAgICBcIipcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic291cmNlXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmljYXRpb24gb2YgYSBkYXRhIHNvdXJjZS4gRm9yIHZlY3RvciBhbmQgcmFzdGVyIHNvdXJjZXMsIGVpdGhlciBUaWxlSlNPTiBvciBhIFVSTCB0byBhIFRpbGVKU09OIG11c3QgYmUgcHJvdmlkZWQuIEZvciBHZW9KU09OIGFuZCB2aWRlbyBzb3VyY2VzLCBhIFVSTCBtdXN0IGJlIHByb3ZpZGVkLlwiXG4gICAgfVxuICB9LFxuICBcInNvdXJjZVwiOiBbXG4gICAgXCJzb3VyY2VfdGlsZVwiLFxuICAgIFwic291cmNlX2dlb2pzb25cIixcbiAgICBcInNvdXJjZV92aWRlb1wiXG4gIF0sXG4gIFwic291cmNlX3RpbGVcIjoge1xuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmVjdG9yXCIsXG4gICAgICAgIFwicmFzdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlRoZSBkYXRhIHR5cGUgb2YgdGhlIHNvdXJjZS5cIlxuICAgIH0sXG4gICAgXCJ1cmxcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgVVJMIHRvIGEgVGlsZUpTT04gcmVzb3VyY2UuIFN1cHBvcnRlZCBwcm90b2NvbHMgYXJlIGBodHRwOmAsIGBodHRwczpgLCBhbmQgYG1hcGJveDovLzxtYXBpZD5gLlwiXG4gICAgfSxcbiAgICBcInRpbGVzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkFuIGFycmF5IG9mIG9uZSBvciBtb3JlIHRpbGUgc291cmNlIFVSTHMsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSB6b29tIGxldmVsIGZvciB3aGljaCB0aWxlcyBhcmUgYXZhaWxhYmxlLCBhcyBpbiB0aGUgVGlsZUpTT04gc3BlYy5cIlxuICAgIH0sXG4gICAgXCJtYXh6b29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJNYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHdoaWNoIHRpbGVzIGFyZSBhdmFpbGFibGUsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLiBEYXRhIGZyb20gdGlsZXMgYXQgdGhlIG1heHpvb20gYXJlIHVzZWQgd2hlbiBkaXNwbGF5aW5nIHRoZSBtYXAgYXQgaGlnaGVyIHpvb20gbGV2ZWxzLlwiXG4gICAgfSxcbiAgICBcInRpbGVTaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDUxMixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gdmlzdWFsIHNpemUgdG8gZGlzcGxheSB0aWxlcyBmb3IgdGhpcyBsYXllci4gT25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBsYXllcnMuXCJcbiAgICB9LFxuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIk90aGVyIGtleXMgdG8gY29uZmlndXJlIHRoZSBkYXRhIHNvdXJjZS5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VfZ2VvanNvblwiOiB7XG4gICAgXCJ0eXBlXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJnZW9qc29uXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiZGF0YVwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCJcbiAgICB9XG4gIH0sXG4gIFwic291cmNlX3ZpZGVvXCI6IHtcbiAgICBcInR5cGVcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpZGVvXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidXJsXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIlVSTHMgdG8gdmlkZW8gY29udGVudCBpbiBvcmRlciBvZiBwcmVmZXJyZWQgZm9ybWF0LlwiXG4gICAgfSxcbiAgICBcImNvb3JkaW5hdGVzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcImxlbmd0aFwiOiA0LFxuICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIlxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgXCJsYXllclwiOiB7XG4gICAgXCJpZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiVW5pcXVlIGxheWVyIG5hbWUuXCJcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiZmlsbFwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJzeW1ib2xcIixcbiAgICAgICAgXCJyYXN0ZXJcIixcbiAgICAgICAgXCJiYWNrZ3JvdW5kXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlJlbmRlcmluZyB0eXBlIG9mIHRoaXMgbGF5ZXIuXCJcbiAgICB9LFxuICAgIFwicmVmXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJSZWZlcmVuY2VzIGFub3RoZXIgbGF5ZXIgdG8gY29weSBgdHlwZWAsIGBzb3VyY2VgLCBgc291cmNlLWxheWVyYCwgYG1pbnpvb21gLCBgbWF4em9vbWAsIGBmaWx0ZXJgLCBhbmQgYGxheW91dGAgcHJvcGVydGllcyBmcm9tLiBUaGlzIGFsbG93cyB0aGUgbGF5ZXJzIHRvIHNoYXJlIHByb2Nlc3NpbmcgYW5kIGJlIG1vcmUgZWZmaWNpZW50LlwiXG4gICAgfSxcbiAgICBcInNvdXJjZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTmFtZSBvZiBhIHNvdXJjZSBkZXNjcmlwdGlvbiB0byBiZSB1c2VkIGZvciB0aGlzIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZS1sYXllclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTGF5ZXIgdG8gdXNlIGZyb20gYSB2ZWN0b3IgdGlsZSBzb3VyY2UuIFJlcXVpcmVkIGlmIHRoZSBzb3VyY2Ugc3VwcG9ydHMgbXVsdGlwbGUgbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAyMixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbGF5ZXIgZ2V0cyBwYXJzZWQgYW5kIGFwcGVhcnMgb24uXCJcbiAgICB9LFxuICAgIFwibWF4em9vbVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWF4aW11bSB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsYXllciBnZXRzIHBhcnNlZCBhbmQgYXBwZWFycyBvbi5cIlxuICAgIH0sXG4gICAgXCJpbnRlcmFjdGl2ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRvY1wiOiBcIkVuYWJsZSBxdWVyeWluZyBvZiBmZWF0dXJlIGRhdGEgZnJvbSB0aGlzIGxheWVyIGZvciBpbnRlcmFjdGl2aXR5LlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlXG4gICAgfSxcbiAgICBcImZpbHRlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBleHByZXNzaW9uIHNwZWNpZnlpbmcgY29uZGl0aW9ucyBvbiBzb3VyY2UgZmVhdHVyZXMuIE9ubHkgZmVhdHVyZXMgdGhhdCBtYXRjaCB0aGUgZmlsdGVyIGFyZSBkaXNwbGF5ZWQuXCJcbiAgICB9LFxuICAgIFwibGF5b3V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImxheW91dFwiLFxuICAgICAgXCJkb2NcIjogXCJMYXlvdXQgcHJvcGVydGllcyBmb3IgdGhlIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInBhaW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkRlZmF1bHQgcGFpbnQgcHJvcGVydGllcyBmb3IgdGhpcyBsYXllci5cIlxuICAgIH0sXG4gICAgXCJwYWludC4qXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkNsYXNzLXNwZWNpZmljIHBhaW50IHByb3BlcnRpZXMgZm9yIHRoaXMgbGF5ZXIuIFRoZSBjbGFzcyBuYW1lIGlzIHRoZSBwYXJ0IGFmdGVyIHRoZSBmaXJzdCBkb3QuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0XCI6IFtcbiAgICBcImxheW91dF9maWxsXCIsXG4gICAgXCJsYXlvdXRfbGluZVwiLFxuICAgIFwibGF5b3V0X3N5bWJvbFwiLFxuICAgIFwibGF5b3V0X3Jhc3RlclwiLFxuICAgIFwibGF5b3V0X2JhY2tncm91bmRcIlxuICBdLFxuICBcImxheW91dF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9maWxsXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9saW5lXCI6IHtcbiAgICBcImxpbmUtY2FwXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJidXR0XCIsXG4gICAgICAgIFwicm91bmRcIixcbiAgICAgICAgXCJzcXVhcmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImJ1dHRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgbGluZSBlbmRpbmdzLlwiXG4gICAgfSxcbiAgICBcImxpbmUtam9pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiYmV2ZWxcIixcbiAgICAgICAgXCJyb3VuZFwiLFxuICAgICAgICBcIm1pdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJtaXRlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiBsaW5lcyB3aGVuIGpvaW5pbmcuXCJcbiAgICB9LFxuICAgIFwibGluZS1taXRlci1saW1pdFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJVc2VkIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCBtaXRlciBqb2lucyB0byBiZXZlbCBqb2lucyBmb3Igc2hhcnAgYW5nbGVzLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcImxpbmUtam9pblwiOiBcIm1pdGVyXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXJvdW5kLWxpbWl0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlVzZWQgdG8gYXV0b21hdGljYWxseSBjb252ZXJ0IHJvdW5kIGpvaW5zIHRvIG1pdGVyIGpvaW5zIGZvciBzaGFsbG93IGFuZ2xlcy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJsaW5lLWpvaW5cIjogXCJyb3VuZFwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3N5bWJvbFwiOiB7XG4gICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgICBcInBvaW50XCIsXG4gICAgICAgICAgXCJsaW5lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJwb2ludFwiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBwbGFjZW1lbnQgcmVsYXRpdmUgdG8gaXRzIGdlb21ldHJ5LiBgbGluZWAgY2FuIG9ubHkgYmUgdXNlZCBvbiBMaW5lU3RyaW5ncyBhbmQgUG9seWdvbnMuXCJcbiAgICB9LFxuICAgIFwic3ltYm9sLW1pbi1kaXN0YW5jZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyNTAsXG4gICAgICBcIm1pbmltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzeW1ib2wgYW5jaG9ycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IFwibGluZVwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwic3ltYm9sLWF2b2lkLWVkZ2VzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgIFwiZG9jXCI6IFwiSWYgdHJ1ZSwgdGhlIHN5bWJvbHMgd2lsbCBub3QgY3Jvc3MgdGlsZSBlZGdlcyB0byBhdm9pZCBtdXR1YWwgY29sbGlzaW9ucy4gUmVjb21tZW5kZWQgaW4gbGF5ZXJzIHRoYXQgZG9uJ3QgaGF2ZSBlbm91Z2ggcGFkZGluZyBpbiB0aGUgdmVjdG9yIHRpbGUgdG8gcHJldmVudCBjb2xsaXNpb25zLCBvciBpZiBpdCBpcyBhIHBvaW50IHN5bWJvbCBsYXllciBwbGFjZWQgYWZ0ZXIgYSBsaW5lIHN5bWJvbCBsYXllci5cIlxuICAgIH0sXG4gICAgXCJpY29uLWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCB0ZXh0LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taWdub3JlLXBsYWNlbWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIHdvbid0IGFmZmVjdCBwbGFjZW1lbnQgb2Ygb3RoZXIgaWNvbnMgYW5kIHRleHQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgaWNvbiwgaW4gc3BhY2VzIHdoZXJlIHRoZSBpY29uIHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIHdoZW4gbWFwIGlzIHJvdGF0ZWQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1tYXgtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIGZhY3RvciB0byBzY2FsZSB0aGUgaWNvbi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkb2NcIjogXCJBIHN0cmluZyB3aXRoIHt0b2tlbnN9IHJlcGxhY2VkLCByZWZlcmVuY2luZyB0aGUgZGF0YSBwcm9wZXJ0eSB0byBwdWxsIGZyb20uXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlXG4gICAgfSxcbiAgICBcImljb24tcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSBpY29uIGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCBpY29uIGJvdW5kaW5nIGJveCB0byBhdm9pZCBpY29uIGNvbGxpc2lvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1rZWVwLXVwcmlnaHRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiBtYXkgYmUgZmxpcHBlZCB0byBwcmV2ZW50IGl0IGZyb20gYmVpbmcgcmVuZGVyZWQgdXBzaWRlLWRvd25cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAge1xuICAgICAgICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSWNvbidzIG9mZnNldCBkaXN0YW5jZS4gVmFsdWVzIGFyZSBbeCwgeV0gd2hlcmUgbmVnYXRpdmVzIGluZGljYXRlIGxlZnQgYW5kIHVwLCByZXNwZWN0aXZlbHkuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIG9yIHRleHQgd2hlbiBtYXAgaXMgcm90YXRlZC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWZpZWxkXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJWYWx1ZSB0byB1c2UgZm9yIGEgdGV4dCBsYWJlbC4gRmVhdHVyZSBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdG9rZW5zIGxpa2Uge2ZpZWxkX25hbWV9LlwiXG4gICAgfSxcbiAgICBcInRleHQtZm9udFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIk9wZW4gU2FucyBSZWd1bGFyLCBBcmlhbCBVbmljb2RlIE1TIFJlZ3VsYXJcIixcbiAgICAgIFwiZG9jXCI6IFwiRm9udCBzdGFjayB0byB1c2UgZm9yIGRpc3BsYXlpbmcgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIHNpemUgdGV4dCB3aWxsIGJlIGxhaWQgb3V0LCB0byBjYWxjdWxhdGUgY29sbGlzaW9ucyB3aXRoLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtbWF4LXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE1LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gbGluZSB3aWR0aCBmb3IgdGV4dCB3cmFwcGluZy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEuMixcbiAgICAgIFwidW5pdHNcIjogXCJlbVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJUZXh0IGxlYWRpbmcgdmFsdWUgZm9yIG11bHRpLWxpbmUgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBrZXJuaW5nIHZhbHVlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtanVzdGlmeVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibGVmdFwiLFxuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcInJpZ2h0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJjZW50ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBqdXN0aWZpY2F0aW9uIG9wdGlvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcImxlZnRcIixcbiAgICAgICAgXCJyaWdodFwiLFxuICAgICAgICBcInRvcFwiLFxuICAgICAgICBcImJvdHRvbVwiLFxuICAgICAgICBcInRvcC1sZWZ0XCIsXG4gICAgICAgIFwidG9wLXJpZ2h0XCIsXG4gICAgICAgIFwiYm90dG9tLWxlZnRcIixcbiAgICAgICAgXCJib3R0b20tcmlnaHRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImNlbnRlclwiLFxuICAgICAgXCJkb2NcIjogXCJXaGljaCBwYXJ0IG9mIHRoZSB0ZXh0IHRvIHBsYWNlIGNsb3Nlc3QgdG8gdGhlIGFuY2hvci5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1hbmdsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiA0NSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIk1heGltdW0gYW5nbGUgY2hhbmdlIGJldHdlZW4gYWRqYWNlbnQgY2hhcmFjdGVycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwic3ltYm9sLXBsYWNlbWVudFwiOiBcImxpbmVcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSB0ZXh0IGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCB0ZXh0IGJvdW5kaW5nIGJveCB0byBhdm9pZCBsYWJlbCBjb2xsaXNpb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQta2VlcC11cHJpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCBtYXkgYmUgZmxpcHBlZCB2ZXJ0aWNhbGx5IHRvIHByZXZlbnQgaXQgZnJvbSBiZWluZyByZW5kZXJlZCB1cHNpZGUtZG93bi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNmb3JtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJub25lXCIsXG4gICAgICAgIFwidXBwZXJjYXNlXCIsXG4gICAgICAgIFwibG93ZXJjYXNlXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJub25lXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmllcyBob3cgdG8gY2FwaXRhbGl6ZSB0ZXh0LCBzaW1pbGFyIHRvIHRoZSBDU1MgYHRleHQtdHJhbnNmb3JtYCBwcm9wZXJ0eS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW9mZnNldFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGRpc3RhbmNlIHRoYXQgdGV4dCBpcyBvZmZzZXQgZnJvbSBpdHMgYW5jaG9yIGhvcml6b250YWxseSBhbmQgdmVydGljYWxseS5cIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwidW5pdHNcIjogXCJlbXNcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwXG4gICAgICBdLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtYWxsb3ctb3ZlcmxhcFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSB0ZXh0IHdpbGwgYmUgdmlzaWJsZSBldmVuIGlmIGl0IGNvbGxpZGVzIHdpdGggb3RoZXIgaWNvbnMgYW5kIGxhYmVscy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCB3b24ndCBhZmZlY3QgcGxhY2VtZW50IG9mIG90aGVyIGljb25zIGFuZCBsYWJlbHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgdGV4dCwgaW4gc3BhY2VzIHdoZXJlIHRoZSB0ZXh0IHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3Jhc3RlclwiOiB7XG4gICAgXCJ2aXNpYmlsaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJ2aXNpYmxlXCIsXG4gICAgICAgIFwibm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwidmlzaWJsZVwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiB0aGlzIGxheWVyLiBgbm9uZWAgaGlkZXMgdGhpcyBsYXllci5cIlxuICAgIH1cbiAgfSxcbiAgXCJmaWx0ZXJcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJ2YWx1ZVwiOiBcIipcIlxuICB9LFxuICBcImZpbHRlcl9vcGVyYXRvclwiOiB7XG4gICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgIFwidmFsdWVzXCI6IFtcbiAgICAgIFwiPT1cIixcbiAgICAgIFwiIT1cIixcbiAgICAgIFwiPlwiLFxuICAgICAgXCI+PVwiLFxuICAgICAgXCI8XCIsXG4gICAgICBcIjw9XCIsXG4gICAgICBcImluXCIsXG4gICAgICBcIiFpblwiLFxuICAgICAgXCJhbGxcIixcbiAgICAgIFwiYW55XCIsXG4gICAgICBcIm5vbmVcIlxuICAgIF1cbiAgfSxcbiAgXCJnZW9tZXRyeV90eXBlXCI6IHtcbiAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgXCJQb2ludFwiLFxuICAgICAgXCJMaW5lU3RyaW5nXCIsXG4gICAgICBcIlBvbHlnb25cIlxuICAgIF1cbiAgfSxcbiAgXCJmdW5jdGlvblwiOiB7XG4gICAgXCJzdG9wc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBhcnJheSBvZiBzdG9wcy5cIixcbiAgICAgIFwidmFsdWVcIjogXCJmdW5jdGlvbl9zdG9wXCJcbiAgICB9LFxuICAgIFwiYmFzZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIlRoZSBleHBvbmVudGlhbCBiYXNlIG9mIHRoZSBpbnRlcnBvbGF0aW9uIGN1cnZlLiBJdCBjb250cm9scyB0aGUgcmF0ZSBhdCB3aGljaCB0aGUgcmVzdWx0IGluY3JlYXNlcy4gSGlnaGVyIHZhbHVlcyBtYWtlIHRoZSByZXN1bHQgaW5jcmVhc2UgbW9yZSB0b3dhcmRzIHRoZSBoaWdoIGVuZCBvZiB0aGUgcmFuZ2UuIFdpdGggYDFgIHRoZSBzdG9wcyBhcmUgaW50ZXJwb2xhdGVkIGxpbmVhcmx5LlwiXG4gICAgfVxuICB9LFxuICBcImZ1bmN0aW9uX3N0b3BcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgIFwidmFsdWVcIjogW1xuICAgICAgXCJudW1iZXJcIixcbiAgICAgIFwiY29sb3JcIlxuICAgIF0sXG4gICAgXCJsZW5ndGhcIjogMixcbiAgICBcImRvY1wiOiBcIlpvb20gbGV2ZWwgYW5kIHZhbHVlIHBhaXIuXCJcbiAgfSxcbiAgXCJwYWludFwiOiBbXG4gICAgXCJwYWludF9maWxsXCIsXG4gICAgXCJwYWludF9saW5lXCIsXG4gICAgXCJwYWludF9zeW1ib2xcIixcbiAgICBcInBhaW50X3Jhc3RlclwiLFxuICAgIFwicGFpbnRfYmFja2dyb3VuZFwiXG4gIF0sXG4gIFwicGFpbnRfZmlsbFwiOiB7XG4gICAgXCJmaWxsLWFudGlhbGlhc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiV2hldGhlciBvciBub3QgdGhlIGZpbGwgc2hvdWxkIGJlIGFudGlhbGlhc2VkLlwiXG4gICAgfSxcbiAgICBcImZpbGwtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgZ2l2ZW4gdG8gdGhlIGZpbGwgY29sb3IuXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJmaWxsLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBjb2xvciBvZiB0aGUgZmlsbC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLW91dGxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG91dGxpbmUgY29sb3Igb2YgdGhlIGZpbGwuIE1hdGNoZXMgdGhlIHZhbHVlIG9mIGBmaWxsLWNvbG9yYCBpZiB1bnNwZWNpZmllZC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIFwiZmlsbC1hbnRpYWxpYXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZ2VvbWV0cnkncyBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiZmlsbC10cmFuc2xhdGVcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBmaWxscy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9saW5lXCI6IHtcbiAgICBcImxpbmUtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGdlb21ldHJ5J3Mgb2Zmc2V0LiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImxpbmUtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwibGluZS13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiU3Ryb2tlIHRoaWNrbmVzcy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWdhcC13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIkRyYXdzIGEgbGluZSBjYXNpbmcgb3V0c2lkZSBvZiBhIGxpbmUncyBhY3R1YWwgcGF0aC4gVmFsdWUgaW5kaWNhdGVzIHRoZSB3aWR0aCBvZiB0aGUgaW5uZXIgZ2FwLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCJcbiAgICB9LFxuICAgIFwibGluZS1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJCbHVyIGFwcGxpZWQgdG8gdGhlIGxpbmUsIGluIHBpeGVscy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWRhc2hhcnJheVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGxlbmd0aHMgb2YgdGhlIGFsdGVybmF0aW5nIGRhc2hlcyBhbmQgZ2FwcyB0aGF0IGZvcm0gdGhlIGRhc2ggcGF0dGVybi4gVGhlIGxlbmd0aHMgYXJlIGxhdGVyIHNjYWxlZCBieSB0aGUgbGluZSB3aWR0aC4gVG8gY29udmVydCBhIGRhc2ggbGVuZ3RoIHRvIHBpeGVscywgbXVsdGlwbHkgdGhlIGxlbmd0aCBieSB0aGUgY3VycmVudCBsaW5lIHdpZHRoLlwiLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJsaW5lIHdpZHRoc1wiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBsaW5lcy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9zeW1ib2xcIjoge1xuICAgIFwiaWNvbi1vcGFjaXR5XCI6IHtcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGljb24gd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiU2NhbGUgZmFjdG9yIGZvciBpY29uLiAxIGlzIG9yaWdpbmFsIHNpemUsIDMgdHJpcGxlcyB0aGUgc2l6ZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uLiBUaGlzIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBzZGYgaWNvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uJ3MgaGFsby4gSWNvbiBoYWxvcyBjYW4gb25seSBiZSB1c2VkIHdpdGggc2RmIGljb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiRGlzdGFuY2Ugb2YgaGFsbyB0byB0aGUgaWNvbiBvdXRsaW5lLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIG91dCB0aGUgaGFsbyB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBpY29uJ3Mgb2Zmc2V0IGRpc3RhbmNlLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJpY29uLXRyYW5zbGF0ZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIHRleHQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxNixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIkZvbnQgc2l6ZS4gSWYgdW5zcGVjaWZpZWQsIHRoZSB0ZXh0IHdpbGwgYmUgYXMgYmlnIGFzIGFsbG93ZWQgYnkgdGhlIGxheWVyIGRlZmluaXRpb24uXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgY29sb3Igd2l0aCB3aGljaCB0aGUgdGV4dCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiIzAwMDAwMFwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSB0ZXh0J3MgaGFsbywgd2hpY2ggaGVscHMgaXQgc3RhbmQgb3V0IGZyb20gYmFja2dyb3VuZHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJEaXN0YW5jZSBvZiBoYWxvIHRvIHRoZSBmb250IG91dGxpbmUuIE1heCB0ZXh0IGhhbG8gd2lkdGggaXMgMS80IG9mIHRoZSBmb250LXNpemUuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWJsdXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBoYWxvJ3MgZmFkZW91dCBkaXN0YW5jZSB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiLFxuICAgICAgICBcInRleHQtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9XG4gIH0sXG4gIFwicGFpbnRfcmFzdGVyXCI6IHtcbiAgICBcInJhc3Rlci1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgaW1hZ2Ugd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcInJhc3Rlci1odWUtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImRvY1wiOiBcIlJvdGF0ZXMgaHVlcyBhcm91bmQgdGhlIGNvbG9yIHdoZWVsLlwiXG4gICAgfSxcbiAgICBcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSW5jcmVhc2Ugb3IgcmVkdWNlIHRoZSBicmlnaHRuZXNzIG9mIHRoZSBpbWFnZS4gVGhlIHZhbHVlIGlzIHRoZSBtaW5pbXVtIGJyaWdodG5lc3MuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgYnJpZ2h0bmVzcyBvZiB0aGUgaW1hZ2UuIFRoZSB2YWx1ZSBpcyB0aGUgbWF4aW11bSBicmlnaHRuZXNzLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLXNhdHVyYXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgc2F0dXJhdGlvbiBvZiB0aGUgaW1hZ2UuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAtMSxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLWNvbnRyYXN0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJJbmNyZWFzZSBvciByZWR1Y2UgdGhlIGNvbnRyYXN0IG9mIHRoZSBpbWFnZS5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IC0xLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIGR1cmF0aW9uIHdoZW4gYSBuZXcgdGlsZSBpcyBhZGRlZC5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcImJhY2tncm91bmQtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGJhY2tncm91bmQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJiYWNrZ3JvdW5kLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJiYWNrZ3JvdW5kLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk9wdGlvbmFsbHkgYW4gaW1hZ2Ugd2hpY2ggaXMgZHJhd24gYXMgdGhlIGJhY2tncm91bmQuXCJcbiAgICB9LFxuICAgIFwiYmFja2dyb3VuZC1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgYmFja2dyb3VuZCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9XG4gIH0sXG4gIFwidHJhbnNpdGlvblwiOiB7XG4gICAgXCJkdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwidW5pdHNcIjogXCJtaWxsaXNlY29uZHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGltZSBhbGxvdHRlZCBmb3IgdHJhbnNpdGlvbnMgdG8gY29tcGxldGUuXCJcbiAgICB9LFxuICAgIFwiZGVsYXlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJMZW5ndGggb2YgdGltZSBiZWZvcmUgYSB0cmFuc2l0aW9uIGJlZ2lucy5cIlxuICAgIH1cbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBsaWdodHdlaWdodCBCdWZmZXIgc2hpbSBmb3IgcGJmIGJyb3dzZXIgYnVpbGRcbi8vIGJhc2VkIG9uIGNvZGUgZnJvbSBnaXRodWIuY29tL2Zlcm9zcy9idWZmZXIgKE1JVC1saWNlbnNlZClcblxubW9kdWxlLmV4cG9ydHMgPSBCdWZmZXI7XG5cbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpO1xuXG52YXIgQnVmZmVyTWV0aG9kcztcblxuZnVuY3Rpb24gQnVmZmVyKGxlbmd0aCkge1xuICAgIHZhciBhcnI7XG4gICAgaWYgKGxlbmd0aCAmJiBsZW5ndGgubGVuZ3RoKSB7XG4gICAgICAgIGFyciA9IGxlbmd0aDtcbiAgICAgICAgbGVuZ3RoID0gYXJyLmxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCB8fCAwKTtcbiAgICBpZiAoYXJyKSBidWYuc2V0KGFycik7XG5cbiAgICBidWYucmVhZFVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkVUludDMyTEU7XG4gICAgYnVmLndyaXRlVUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG4gICAgYnVmLnJlYWRJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkSW50MzJMRTtcbiAgICBidWYud3JpdGVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEU7XG4gICAgYnVmLnJlYWRGbG9hdExFID0gQnVmZmVyTWV0aG9kcy5yZWFkRmxvYXRMRTtcbiAgICBidWYud3JpdGVGbG9hdExFID0gQnVmZmVyTWV0aG9kcy53cml0ZUZsb2F0TEU7XG4gICAgYnVmLnJlYWREb3VibGVMRSA9IEJ1ZmZlck1ldGhvZHMucmVhZERvdWJsZUxFO1xuICAgIGJ1Zi53cml0ZURvdWJsZUxFID0gQnVmZmVyTWV0aG9kcy53cml0ZURvdWJsZUxFO1xuICAgIGJ1Zi50b1N0cmluZyA9IEJ1ZmZlck1ldGhvZHMudG9TdHJpbmc7XG4gICAgYnVmLndyaXRlID0gQnVmZmVyTWV0aG9kcy53cml0ZTtcbiAgICBidWYuc2xpY2UgPSBCdWZmZXJNZXRob2RzLnNsaWNlO1xuICAgIGJ1Zi5jb3B5ID0gQnVmZmVyTWV0aG9kcy5jb3B5O1xuXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWU7XG4gICAgcmV0dXJuIGJ1Zjtcbn1cblxudmFyIGxhc3RTdHIsIGxhc3RTdHJFbmNvZGVkO1xuXG5CdWZmZXJNZXRob2RzID0ge1xuICAgIHJlYWRVSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSAqIDB4MTAwMDAwMCk7XG4gICAgfSxcblxuICAgIHdyaXRlVUludDMyTEU6IGZ1bmN0aW9uKHZhbCwgcG9zKSB7XG4gICAgICAgIHRoaXNbcG9zXSA9IHZhbDtcbiAgICAgICAgdGhpc1twb3MgKyAxXSA9ICh2YWwgPj4+IDgpO1xuICAgICAgICB0aGlzW3BvcyArIDJdID0gKHZhbCA+Pj4gMTYpO1xuICAgICAgICB0aGlzW3BvcyArIDNdID0gKHZhbCA+Pj4gMjQpO1xuICAgIH0sXG5cbiAgICByZWFkSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSA8PCAyNCk7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdExFOiAgZnVuY3Rpb24ocG9zKSB7IHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgcmVhZERvdWJsZUxFOiBmdW5jdGlvbihwb3MpIHsgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHdyaXRlRmxvYXRMRTogIGZ1bmN0aW9uKHZhbCwgcG9zKSB7IHJldHVybiBpZWVlNzU0LndyaXRlKHRoaXMsIHZhbCwgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgd3JpdGVEb3VibGVMRTogZnVuY3Rpb24odmFsLCBwb3MpIHsgcmV0dXJuIGllZWU3NTQud3JpdGUodGhpcywgdmFsLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHRvU3RyaW5nOiBmdW5jdGlvbihlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICAgICAgICB2YXIgc3RyID0gJycsXG4gICAgICAgICAgICB0bXAgPSAnJztcblxuICAgICAgICBzdGFydCA9IHN0YXJ0IHx8IDA7XG4gICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGVuZ3RoLCBlbmQgfHwgdGhpcy5sZW5ndGgpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2ggPSB0aGlzW2ldO1xuICAgICAgICAgICAgaWYgKGNoIDw9IDB4N0YpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gZGVjb2RlVVJJQ29tcG9uZW50KHRtcCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTtcbiAgICAgICAgICAgICAgICB0bXAgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG1wICs9ICclJyArIGNoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0ciArPSBkZWNvZGVVUklDb21wb25lbnQodG1wKTtcblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICB3cml0ZTogZnVuY3Rpb24oc3RyLCBwb3MpIHtcbiAgICAgICAgdmFyIGJ5dGVzID0gc3RyID09PSBsYXN0U3RyID8gbGFzdFN0ckVuY29kZWQgOiBlbmNvZGVTdHJpbmcoc3RyKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpc1twb3MgKyBpXSA9IGJ5dGVzW2ldO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNsaWNlOiBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpO1xuICAgIH0sXG5cbiAgICBjb3B5OiBmdW5jdGlvbihidWYsIHBvcykge1xuICAgICAgICBwb3MgPSBwb3MgfHwgMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBidWZbcG9zICsgaV0gPSB0aGlzW2ldO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgbGFzdFN0ciA9IHN0cjtcbiAgICBsYXN0U3RyRW5jb2RlZCA9IGVuY29kZVN0cmluZyhzdHIpO1xuICAgIHJldHVybiBsYXN0U3RyRW5jb2RlZC5sZW5ndGg7XG59O1xuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbihidWYpIHtcbiAgICByZXR1cm4gISEoYnVmICYmIGJ1Zi5faXNCdWZmZXIpO1xufTtcblxuZnVuY3Rpb24gZW5jb2RlU3RyaW5nKHN0cikge1xuICAgIHZhciBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICBieXRlcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGMsIGxlYWQ7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSk7IC8vIGNvZGUgcG9pbnRcblxuICAgICAgICBpZiAoYyA+IDB4RDdGRiAmJiBjIDwgMHhFMDAwKSB7XG5cbiAgICAgICAgICAgIGlmIChsZWFkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGMgPCAweERDMDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IGM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYyA9IGxlYWQgLSAweEQ4MDAgPDwgMTAgfCBjIC0gMHhEQzAwIHwgMHgxMDAwMDtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjID4gMHhEQkZGIHx8IChpICsgMSA9PT0gbGVuZ3RoKSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICBlbHNlIGxlYWQgPSBjO1xuXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmIChsZWFkKSB7XG4gICAgICAgICAgICBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpO1xuICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODApIGJ5dGVzLnB1c2goYyk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDgwMCkgYnl0ZXMucHVzaChjID4+IDB4NiB8IDB4QzAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDEwMDAwKSBieXRlcy5wdXNoKGMgPj4gMHhDIHwgMHhFMCwgYyA+PiAweDYgJiAweDNGIHwgMHg4MCwgYyAmIDB4M0YgfCAweDgwKTtcbiAgICAgICAgZWxzZSBieXRlcy5wdXNoKGMgPj4gMHgxMiB8IDB4RjAsIGMgPj4gMHhDICYgMHgzRiB8IDB4ODAsIGMgPj4gMHg2ICYgMHgzRiB8IDB4ODAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgfVxuICAgIHJldHVybiBieXRlcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBQYmY7XG5cbnZhciBCdWZmZXIgPSBnbG9iYWwuQnVmZmVyIHx8IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbmZ1bmN0aW9uIFBiZihidWYpIHtcbiAgICB0aGlzLmJ1ZiA9ICFCdWZmZXIuaXNCdWZmZXIoYnVmKSA/IG5ldyBCdWZmZXIoYnVmIHx8IDApIDogYnVmO1xuICAgIHRoaXMucG9zID0gMDtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMuYnVmLmxlbmd0aDtcbn1cblxuUGJmLlZhcmludCAgPSAwOyAvLyB2YXJpbnQ6IGludDMyLCBpbnQ2NCwgdWludDMyLCB1aW50NjQsIHNpbnQzMiwgc2ludDY0LCBib29sLCBlbnVtXG5QYmYuRml4ZWQ2NCA9IDE7IC8vIDY0LWJpdDogZG91YmxlLCBmaXhlZDY0LCBzZml4ZWQ2NFxuUGJmLkJ5dGVzICAgPSAyOyAvLyBsZW5ndGgtZGVsaW1pdGVkOiBzdHJpbmcsIGJ5dGVzLCBlbWJlZGRlZCBtZXNzYWdlcywgcGFja2VkIHJlcGVhdGVkIGZpZWxkc1xuUGJmLkZpeGVkMzIgPSA1OyAvLyAzMi1iaXQ6IGZsb2F0LCBmaXhlZDMyLCBzZml4ZWQzMlxuXG52YXIgU0hJRlRfTEVGVF8zMiA9ICgxIDw8IDE2KSAqICgxIDw8IDE2KSxcbiAgICBTSElGVF9SSUdIVF8zMiA9IDEgLyBTSElGVF9MRUZUXzMyLFxuICAgIFBPV18yXzYzID0gTWF0aC5wb3coMiwgNjMpO1xuXG5QYmYucHJvdG90eXBlID0ge1xuXG4gICAgZGVzdHJveTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuYnVmID0gbnVsbDtcbiAgICB9LFxuXG4gICAgLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHJlYWRGaWVsZHM6IGZ1bmN0aW9uKHJlYWRGaWVsZCwgcmVzdWx0LCBlbmQpIHtcbiAgICAgICAgZW5kID0gZW5kIHx8IHRoaXMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludCgpLFxuICAgICAgICAgICAgICAgIHRhZyA9IHZhbCA+PiAzLFxuICAgICAgICAgICAgICAgIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG5cbiAgICAgICAgICAgIHJlYWRGaWVsZCh0YWcsIHJlc3VsdCwgdGhpcyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gc3RhcnRQb3MpIHRoaXMuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIHJlYWRNZXNzYWdlOiBmdW5jdGlvbihyZWFkRmllbGQsIHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkRmllbGRzKHJlYWRGaWVsZCwgcmVzdWx0LCB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zKTtcbiAgICB9LFxuXG4gICAgcmVhZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZFVJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFNGaXhlZDMyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgLy8gNjQtYml0IGludCBoYW5kbGluZyBpcyBiYXNlZCBvbiBnaXRodWIuY29tL2Rwdy9ub2RlLWJ1ZmZlci1tb3JlLWludHMgKE1JVC1saWNlbnNlZClcblxuICAgIHJlYWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRVSW50MzJMRSh0aGlzLnBvcykgKyB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRTRml4ZWQ2NDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MpICsgdGhpcy5idWYucmVhZEludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkRmxvYXRMRSh0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZERvdWJsZUxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBidWYgPSB0aGlzLmJ1ZixcbiAgICAgICAgICAgIHZhbCwgYiwgYjAsIGIxLCBiMiwgYjM7XG5cbiAgICAgICAgYjAgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMCA8IDB4ODApIHJldHVybiBiMDsgICAgICAgICAgICAgICAgIGIwID0gYjAgJiAweDdmO1xuICAgICAgICBiMSA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIxIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgPDwgNzsgICAgICAgYjEgPSAoYjEgJiAweDdmKSA8PCA3O1xuICAgICAgICBiMiA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIyIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgfCBiMiA8PCAxNDsgYjIgPSAoYjIgJiAweDdmKSA8PCAxNDtcbiAgICAgICAgYjMgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMyA8IDB4ODApIHJldHVybiBiMCB8IGIxIHwgYjIgfCBiMyA8PCAyMTtcblxuICAgICAgICB2YWwgPSBiMCB8IGIxIHwgYjIgfCAoYjMgJiAweDdmKSA8PCAyMTtcblxuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDA7ICAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwOyAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4NDAwMDAwMDAwMDA7ICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MjAwMDAwMDAwMDAwMDsgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDAwMDAwMDAwOyAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwMDAwMDAwMDsgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgdmFyaW50IG5vdCBtb3JlIHRoYW4gMTAgYnl0ZXMnKTtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICB2YWwgPSB0aGlzLnJlYWRWYXJpbnQoKTtcblxuICAgICAgICBpZiAodmFsIDwgUE9XXzJfNjMpIHJldHVybiB2YWw7XG5cbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zIC0gMjtcbiAgICAgICAgd2hpbGUgKHRoaXMuYnVmW3Bvc10gPT09IDB4ZmYpIHBvcy0tO1xuICAgICAgICBpZiAocG9zIDwgc3RhcnRQb3MpIHBvcyA9IHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhbCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zIC0gc3RhcnRQb3MgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBiID0gfnRoaXMuYnVmW3N0YXJ0UG9zICsgaV0gJiAweDdmO1xuICAgICAgICAgICAgdmFsICs9IGkgPCA0ID8gYiA8PCBpICogNyA6IGIgKiBNYXRoLnBvdygyLCBpICogNyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLXZhbCAtIDE7XG4gICAgfSxcblxuICAgIHJlYWRTVmFyaW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG51bSA9IHRoaXMucmVhZFZhcmludCgpO1xuICAgICAgICByZXR1cm4gbnVtICUgMiA9PT0gMSA/IChudW0gKyAxKSAvIC0yIDogbnVtIC8gMjsgLy8gemlnemFnIGVuY29kaW5nXG4gICAgfSxcblxuICAgIHJlYWRCb29sZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpO1xuICAgIH0sXG5cbiAgICByZWFkU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBzdHIgPSB0aGlzLmJ1Zi50b1N0cmluZygndXRmOCcsIHRoaXMucG9zLCBlbmQpO1xuICAgICAgICB0aGlzLnBvcyA9IGVuZDtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuXG4gICAgcmVhZEJ5dGVzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBidWZmZXIgPSB0aGlzLmJ1Zi5zbGljZSh0aGlzLnBvcywgZW5kKTtcbiAgICAgICAgdGhpcy5wb3MgPSBlbmQ7XG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfSxcblxuICAgIC8vIHZlcmJvc2UgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnM7IGRvZXNuJ3QgYWZmZWN0IGd6aXBwZWQgc2l6ZVxuXG4gICAgcmVhZFBhY2tlZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRWYXJpbnQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU1ZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEJvb2xlYW46IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkQm9vbGVhbigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRGbG9hdCgpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRG91YmxlKCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsIGFyciA9IFtdO1xuICAgICAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcblxuICAgIHNraXA6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHZhbCAmIDB4NztcbiAgICAgICAgaWYgKHR5cGUgPT09IFBiZi5WYXJpbnQpIHdoaWxlICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA+IDB4N2YpIHt9XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT09IFBiZi5CeXRlcykgdGhpcy5wb3MgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zO1xuICAgICAgICBlbHNlIGlmICh0eXBlID09PSBQYmYuRml4ZWQzMikgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkNjQpIHRoaXMucG9zICs9IDg7XG4gICAgICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdVbmltcGxlbWVudGVkIHR5cGU6ICcgKyB0eXBlKTtcbiAgICB9LFxuXG4gICAgLy8gPT09IFdSSVRJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHdyaXRlVGFnOiBmdW5jdGlvbih0YWcsIHR5cGUpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludCgodGFnIDw8IDMpIHwgdHlwZSk7XG4gICAgfSxcblxuICAgIHJlYWxsb2M6IGZ1bmN0aW9uKG1pbikge1xuICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfHwgMTY7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aCA8IHRoaXMucG9zICsgbWluKSBsZW5ndGggKj0gMjtcblxuICAgICAgICBpZiAobGVuZ3RoICE9PSB0aGlzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYnVmLmNvcHkoYnVmKTtcbiAgICAgICAgICAgIHRoaXMuYnVmID0gYnVmO1xuICAgICAgICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZmluaXNoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLnBvcztcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcy5idWYuc2xpY2UoMCwgdGhpcy5sZW5ndGgpO1xuICAgIH0sXG5cbiAgICB3cml0ZUZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlVUludDMyTEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlU0ZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRSh2YWwsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICB9LFxuXG4gICAgd3JpdGVGaXhlZDY0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUludDMyTEUodmFsICYgLTEsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVVSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVTRml4ZWQ2NDogZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVJbnQzMkxFKHZhbCAmIC0xLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YWwgPSArdmFsO1xuXG4gICAgICAgIGlmICh2YWwgPD0gMHg3Zikge1xuICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWw7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgzZmZmKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2MoMik7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAwKSAmIDB4N2YpIHwgMHg4MDtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDcpICYgMHg3Zik7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgxZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygzKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHZhbCA8PSAweGZmZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYyg0KTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAyMSkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zO1xuICAgICAgICAgICAgd2hpbGUgKHZhbCA+PSAweDgwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKHZhbCAmIDB4ZmYpIHwgMHg4MDtcbiAgICAgICAgICAgICAgICB2YWwgLz0gMHg4MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygxKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gdmFsIHwgMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyAtIHBvcyA+IDEwKSB0aHJvdyBuZXcgRXJyb3IoJ0dpdmVuIHZhcmludCBkb2VzblxcJ3QgZml0IGludG8gMTAgYnl0ZXMnKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZVNWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCA8IDAgPyAtdmFsICogMiAtIDEgOiB2YWwgKiAyKTtcbiAgICB9LFxuXG4gICAgd3JpdGVCb29sZWFuOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludChCb29sZWFuKHZhbCkpO1xuICAgIH0sXG5cbiAgICB3cml0ZVN0cmluZzogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgIHN0ciA9IFN0cmluZyhzdHIpO1xuICAgICAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuYnl0ZUxlbmd0aChzdHIpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KGJ5dGVzKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGJ5dGVzKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGUoc3RyLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IGJ5dGVzO1xuICAgIH0sXG5cbiAgICB3cml0ZUZsb2F0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUZsb2F0TEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlRG91YmxlOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZURvdWJsZUxFKHZhbCwgdGhpcy5wb3MpO1xuICAgICAgICB0aGlzLnBvcyArPSA4O1xuICAgIH0sXG5cbiAgICB3cml0ZUJ5dGVzOiBmdW5jdGlvbihidWZmZXIpIHtcbiAgICAgICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGxlbik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHRoaXMuYnVmW3RoaXMucG9zKytdID0gYnVmZmVyW2ldO1xuICAgIH0sXG5cbiAgICB3cml0ZU1lc3NhZ2U6IGZ1bmN0aW9uKHRhZywgZm4sIG9iaikge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkJ5dGVzKTtcblxuICAgICAgICB0aGlzLnBvcysrOyAvLyByZXNlcnZlIDEgYnl0ZSBmb3Igc2hvcnQgbWVzc2FnZSBsZW5ndGhcblxuICAgICAgICAvLyB3cml0ZSB0aGUgbWVzc2FnZSBkaXJlY3RseSB0byB0aGUgYnVmZmVyIGFuZCBzZWUgaG93IG11Y2ggd2FzIHdyaXR0ZW5cbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG4gICAgICAgIGZuKG9iaiwgdGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLnBvcyAtIHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhciB2YXJpbnRMZW4gPVxuICAgICAgICAgICAgbGVuIDw9IDB4N2YgPyAxIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDNmZmYgPyAyIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDFmZmZmZiA/IDMgOlxuICAgICAgICAgICAgbGVuIDw9IDB4ZmZmZmZmZiA/IDQgOiBNYXRoLmNlaWwoTWF0aC5sb2cobGVuKSAvIChNYXRoLkxOMiAqIDcpKTtcblxuICAgICAgICAvLyBpZiAxIGJ5dGUgaXNuJ3QgZW5vdWdoIGZvciBlbmNvZGluZyBtZXNzYWdlIGxlbmd0aCwgc2hpZnQgdGhlIGRhdGEgdG8gdGhlIHJpZ2h0XG4gICAgICAgIGlmICh2YXJpbnRMZW4gPiAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2ModmFyaW50TGVuIC0gMSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5wb3MgLSAxOyBpID49IHN0YXJ0UG9zOyBpLS0pIHRoaXMuYnVmW2kgKyB2YXJpbnRMZW4gLSAxXSA9IHRoaXMuYnVmW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluYWxseSwgd3JpdGUgdGhlIG1lc3NhZ2UgbGVuZ3RoIGluIHRoZSByZXNlcnZlZCBwbGFjZSBhbmQgcmVzdG9yZSB0aGUgcG9zaXRpb25cbiAgICAgICAgdGhpcy5wb3MgPSBzdGFydFBvcyAtIDE7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gbGVuO1xuICAgIH0sXG5cbiAgICB3cml0ZVBhY2tlZFZhcmludDogICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkVmFyaW50LCBhcnIpOyAgIH0sXG4gICAgd3JpdGVQYWNrZWRTVmFyaW50OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZFNWYXJpbnQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkQm9vbGVhbjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRCb29sZWFuLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZEZsb2F0OiAgICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkRmxvYXQsIGFycik7ICAgIH0sXG4gICAgd3JpdGVQYWNrZWREb3VibGU6ICAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZERvdWJsZSwgYXJyKTsgICB9LFxuICAgIHdyaXRlUGFja2VkRml4ZWQzMjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRGaXhlZDMyLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZFNGaXhlZDMyOiBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkU0ZpeGVkMzIsIGFycik7IH0sXG4gICAgd3JpdGVQYWNrZWRGaXhlZDY0OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZEZpeGVkNjQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRTRml4ZWQ2NCwgYXJyKTsgfSxcblxuICAgIHdyaXRlQnl0ZXNGaWVsZDogZnVuY3Rpb24odGFnLCBidWZmZXIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVCeXRlcyhidWZmZXIpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDMyKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQzMih2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDY0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQ2NCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlU1ZhcmludCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVTdHJpbmdGaWVsZDogZnVuY3Rpb24odGFnLCBzdHIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVTdHJpbmcoc3RyKTtcbiAgICB9LFxuICAgIHdyaXRlRmxvYXRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDMyKTtcbiAgICAgICAgdGhpcy53cml0ZUZsb2F0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZURvdWJsZUZpZWxkOiBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkNjQpO1xuICAgICAgICB0aGlzLndyaXRlRG91YmxlKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZUJvb2xlYW5GaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludEZpZWxkKHRhZywgQm9vbGVhbih2YWwpKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiB3cml0ZVBhY2tlZFZhcmludChhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVWYXJpbnQoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNWYXJpbnQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTVmFyaW50KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZsb2F0KGFyciwgcGJmKSAgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGbG9hdChhcnJbaV0pOyAgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZERvdWJsZShhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVEb3VibGUoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEJvb2xlYW4oYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVCb29sZWFuKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkMzIoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDMyKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDMyKGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQzMihhcnJbaV0pOyB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkNjQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDY0KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDY0KGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQ2NChhcnJbaV0pOyB9XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBvaW50O1xuXG5mdW5jdGlvbiBQb2ludCh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xufVxuXG5Qb2ludC5wcm90b3R5cGUgPSB7XG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgdGhpcy55KTsgfSxcblxuICAgIGFkZDogICAgIGZ1bmN0aW9uKHApIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHApOyAgICAgfSxcbiAgICBzdWI6ICAgICBmdW5jdGlvbihwKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3N1YihwKTsgICAgIH0sXG4gICAgbXVsdDogICAgZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0KGspOyAgICB9LFxuICAgIGRpdjogICAgIGZ1bmN0aW9uKGspIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2KGspOyAgICAgfSxcbiAgICByb3RhdGU6ICBmdW5jdGlvbihhKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZShhKTsgIH0sXG4gICAgbWF0TXVsdDogZnVuY3Rpb24obSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tYXRNdWx0KG0pOyB9LFxuICAgIHVuaXQ6ICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCk7IH0sXG4gICAgcGVycDogICAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKTsgfSxcbiAgICByb3VuZDogICBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTsgfSxcblxuICAgIG1hZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQodGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55KTtcbiAgICB9LFxuXG4gICAgZXF1YWxzOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnggPT09IHAueCAmJlxuICAgICAgICAgICAgICAgdGhpcy55ID09PSBwLnk7XG4gICAgfSxcblxuICAgIGRpc3Q6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIocCkpO1xuICAgIH0sXG5cbiAgICBkaXN0U3FyOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHZhciBkeCA9IHAueCAtIHRoaXMueCxcbiAgICAgICAgICAgIGR5ID0gcC55IC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG4gICAgfSxcblxuICAgIGFuZ2xlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpO1xuICAgIH0sXG5cbiAgICBhbmdsZVRvOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMueSAtIGIueSwgdGhpcy54IC0gYi54KTtcbiAgICB9LFxuXG4gICAgYW5nbGVXaXRoOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFuZ2xlV2l0aFNlcChiLngsIGIueSk7XG4gICAgfSxcblxuICAgIC8vIEZpbmQgdGhlIGFuZ2xlIG9mIHRoZSB0d28gdmVjdG9ycywgc29sdmluZyB0aGUgZm9ybXVsYSBmb3IgdGhlIGNyb3NzIHByb2R1Y3QgYSB4IGIgPSB8YXx8YnxzaW4ozrgpIGZvciDOuC5cbiAgICBhbmdsZVdpdGhTZXA6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoXG4gICAgICAgICAgICB0aGlzLnggKiB5IC0gdGhpcy55ICogeCxcbiAgICAgICAgICAgIHRoaXMueCAqIHggKyB0aGlzLnkgKiB5KTtcbiAgICB9LFxuXG4gICAgX21hdE11bHQ6IGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgdmFyIHggPSBtWzBdICogdGhpcy54ICsgbVsxXSAqIHRoaXMueSxcbiAgICAgICAgICAgIHkgPSBtWzJdICogdGhpcy54ICsgbVszXSAqIHRoaXMueTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hZGQ6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54ICs9IHAueDtcbiAgICAgICAgdGhpcy55ICs9IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9zdWI6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54IC09IHAueDtcbiAgICAgICAgdGhpcy55IC09IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9tdWx0OiBmdW5jdGlvbihrKSB7XG4gICAgICAgIHRoaXMueCAqPSBrO1xuICAgICAgICB0aGlzLnkgKj0gaztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kaXY6IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdGhpcy54IC89IGs7XG4gICAgICAgIHRoaXMueSAvPSBrO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3VuaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9kaXYodGhpcy5tYWcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcGVycDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55O1xuICAgICAgICB0aGlzLnkgPSB0aGlzLng7XG4gICAgICAgIHRoaXMueCA9IC15O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdGF0ZTogZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgICAgIHggPSBjb3MgKiB0aGlzLnggLSBzaW4gKiB0aGlzLnksXG4gICAgICAgICAgICB5ID0gc2luICogdGhpcy54ICsgY29zICogdGhpcy55O1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgUG9pbnQgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblBvaW50LmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoYVswXSwgYVsxXSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufTtcbiIsIi8qXG4gKGMpIDIwMTMsIFZsYWRpbWlyIEFnYWZvbmtpblxuIFJCdXNoLCBhIEphdmFTY3JpcHQgbGlicmFyeSBmb3IgaGlnaC1wZXJmb3JtYW5jZSAyRCBzcGF0aWFsIGluZGV4aW5nIG9mIHBvaW50cyBhbmQgcmVjdGFuZ2xlcy5cbiBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9yYnVzaFxuKi9cblxuKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpIHtcblxuICAgIC8vIGpzaGludCBuZXdjYXA6IGZhbHNlLCB2YWxpZHRoaXM6IHRydWVcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgcmJ1c2gpKSByZXR1cm4gbmV3IHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCk7XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgICB0b0JCb3ggPSB0aGlzLnRvQkJveDtcblxuICAgICAgICBpZiAoIWludGVyc2VjdHMoYmJveCwgbm9kZS5iYm94KSkgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICB2YXIgbm9kZXNUb1NlYXJjaCA9IFtdLFxuICAgICAgICAgICAgaSwgbGVuLCBjaGlsZCwgY2hpbGRCQm94O1xuXG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgY2hpbGRCQm94ID0gbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3g7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJzZWN0cyhiYm94LCBjaGlsZEJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGFpbnMoYmJveCwgY2hpbGRCQm94KSkgdGhpcy5fYWxsKGNoaWxkLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBjb2xsaWRlczogZnVuY3Rpb24gKGJib3gpIHtcblxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZGF0YSxcbiAgICAgICAgICAgIHRvQkJveCA9IHRoaXMudG9CQm94O1xuXG4gICAgICAgIGlmICghaW50ZXJzZWN0cyhiYm94LCBub2RlLmJib3gpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZC5iYm94O1xuXG4gICAgICAgICAgICAgICAgaWYgKGludGVyc2VjdHMoYmJveCwgY2hpbGRCQm94KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IGNvbnRhaW5zKGJib3gsIGNoaWxkQkJveCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1RvU2VhcmNoLnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICBsb2FkOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBpZiAoIShkYXRhICYmIGRhdGEubGVuZ3RoKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgdGhpcy5fbWluRW50cmllcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluc2VydChkYXRhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVjdXJzaXZlbHkgYnVpbGQgdGhlIHRyZWUgd2l0aCB0aGUgZ2l2ZW4gZGF0YSBmcm9tIHN0cmF0Y2ggdXNpbmcgT01UIGFsZ29yaXRobVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX2J1aWxkKGRhdGEuc2xpY2UoKSwgMCwgZGF0YS5sZW5ndGggLSAxLCAwKTtcblxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHNhdmUgYXMgaXMgaWYgdHJlZSBpcyBlbXB0eVxuICAgICAgICAgICAgdGhpcy5kYXRhID0gbm9kZTtcblxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPT09IG5vZGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICAvLyBzcGxpdCByb290IGlmIHRyZWVzIGhhdmUgdGhlIHNhbWUgaGVpZ2h0XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLCBub2RlKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPCBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgdHJlZXMgaWYgaW5zZXJ0ZWQgb25lIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgIHZhciB0bXBOb2RlID0gdGhpcy5kYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IHRtcE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGluc2VydCB0aGUgc21hbGwgdHJlZSBpbnRvIHRoZSBsYXJnZSB0cmVlIGF0IGFwcHJvcHJpYXRlIGxldmVsXG4gICAgICAgICAgICB0aGlzLl9pbnNlcnQobm9kZSwgdGhpcy5kYXRhLmhlaWdodCAtIG5vZGUuaGVpZ2h0IC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBpZiAoaXRlbSkgdGhpcy5faW5zZXJ0KGl0ZW0sIHRoaXMuZGF0YS5oZWlnaHQgLSAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgICAgIGJib3g6IGVtcHR5KCksXG4gICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICByZW1vdmU6IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBub2RlLmNoaWxkcmVuLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiBjb250YWlucyhub2RlLmJib3gsIGJib3gpKSB7IC8vIGdvIGRvd25cbiAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bMF07XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50KSB7IC8vIGdvIHJpZ2h0XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBwYXJlbnQuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9IGVsc2Ugbm9kZSA9IG51bGw7IC8vIG5vdGhpbmcgZm91bmRcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICB0b0JCb3g6IGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBpdGVtOyB9LFxuXG4gICAgY29tcGFyZU1pblg6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhWzBdIC0gYlswXTsgfSxcbiAgICBjb21wYXJlTWluWTogZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGFbMV0gLSBiWzFdOyB9LFxuXG4gICAgdG9KU09OOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmRhdGE7IH0sXG5cbiAgICBmcm9tSlNPTjogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hbGw6IGZ1bmN0aW9uIChub2RlLCByZXN1bHQpIHtcbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXTtcbiAgICAgICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgbm9kZS5jaGlsZHJlbik7XG4gICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaC5hcHBseShub2Rlc1RvU2VhcmNoLCBub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgX2J1aWxkOiBmdW5jdGlvbiAoaXRlbXMsIGxlZnQsIHJpZ2h0LCBoZWlnaHQpIHtcblxuICAgICAgICB2YXIgTiA9IHJpZ2h0IC0gbGVmdCArIDEsXG4gICAgICAgICAgICBNID0gdGhpcy5fbWF4RW50cmllcyxcbiAgICAgICAgICAgIG5vZGU7XG5cbiAgICAgICAgaWYgKE4gPD0gTSkge1xuICAgICAgICAgICAgLy8gcmVhY2hlZCBsZWFmIGxldmVsOyByZXR1cm4gbGVhZlxuICAgICAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgICAgICBjaGlsZHJlbjogaXRlbXMuc2xpY2UobGVmdCwgcmlnaHQgKyAxKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgICAgICAgICAgYmJveDogbnVsbCxcbiAgICAgICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgLy8gdGFyZ2V0IGhlaWdodCBvZiB0aGUgYnVsay1sb2FkZWQgdHJlZVxuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGgubG9nKE4pIC8gTWF0aC5sb2coTSkpO1xuXG4gICAgICAgICAgICAvLyB0YXJnZXQgbnVtYmVyIG9mIHJvb3QgZW50cmllcyB0byBtYXhpbWl6ZSBzdG9yYWdlIHV0aWxpemF0aW9uXG4gICAgICAgICAgICBNID0gTWF0aC5jZWlsKE4gLyBNYXRoLnBvdyhNLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPIGVsaW1pbmF0ZSByZWN1cnNpb24/XG5cbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgYmJveDogbnVsbFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNwbGl0IHRoZSBpdGVtcyBpbnRvIE0gbW9zdGx5IHNxdWFyZSB0aWxlc1xuXG4gICAgICAgIHZhciBOMiA9IE1hdGguY2VpbChOIC8gTSksXG4gICAgICAgICAgICBOMSA9IE4yICogTWF0aC5jZWlsKE1hdGguc3FydChNKSksXG4gICAgICAgICAgICBpLCBqLCByaWdodDIsIHJpZ2h0MztcblxuICAgICAgICBtdWx0aVNlbGVjdChpdGVtcywgbGVmdCwgcmlnaHQsIE4xLCB0aGlzLmNvbXBhcmVNaW5YKTtcblxuICAgICAgICBmb3IgKGkgPSBsZWZ0OyBpIDw9IHJpZ2h0OyBpICs9IE4xKSB7XG5cbiAgICAgICAgICAgIHJpZ2h0MiA9IE1hdGgubWluKGkgKyBOMSAtIDEsIHJpZ2h0KTtcblxuICAgICAgICAgICAgbXVsdGlTZWxlY3QoaXRlbXMsIGksIHJpZ2h0MiwgTjIsIHRoaXMuY29tcGFyZU1pblkpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSBpOyBqIDw9IHJpZ2h0MjsgaiArPSBOMikge1xuXG4gICAgICAgICAgICAgICAgcmlnaHQzID0gTWF0aC5taW4oaiArIE4yIC0gMSwgcmlnaHQyKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgZWFjaCBlbnRyeSByZWN1cnNpdmVseVxuICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4ucHVzaCh0aGlzLl9idWlsZChpdGVtcywgaiwgcmlnaHQzLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjYWxjQkJveChub2RlLCB0aGlzLnRvQkJveCk7XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9jaG9vc2VTdWJ0cmVlOiBmdW5jdGlvbiAoYmJveCwgbm9kZSwgbGV2ZWwsIHBhdGgpIHtcblxuICAgICAgICB2YXIgaSwgbGVuLCBjaGlsZCwgdGFyZ2V0Tm9kZSwgYXJlYSwgZW5sYXJnZW1lbnQsIG1pbkFyZWEsIG1pbkVubGFyZ2VtZW50O1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYgfHwgcGF0aC5sZW5ndGggLSAxID09PSBsZXZlbCkgYnJlYWs7XG5cbiAgICAgICAgICAgIG1pbkFyZWEgPSBtaW5FbmxhcmdlbWVudCA9IEluZmluaXR5O1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShjaGlsZC5iYm94KTtcbiAgICAgICAgICAgICAgICBlbmxhcmdlbWVudCA9IGVubGFyZ2VkQXJlYShiYm94LCBjaGlsZC5iYm94KSAtIGFyZWE7XG5cbiAgICAgICAgICAgICAgICAvLyBjaG9vc2UgZW50cnkgd2l0aCB0aGUgbGVhc3QgYXJlYSBlbmxhcmdlbWVudFxuICAgICAgICAgICAgICAgIGlmIChlbmxhcmdlbWVudCA8IG1pbkVubGFyZ2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkVubGFyZ2VtZW50ID0gZW5sYXJnZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVubGFyZ2VtZW50ID09PSBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIG9uZSB3aXRoIHRoZSBzbWFsbGVzdCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSB0YXJnZXROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9pbnNlcnQ6IGZ1bmN0aW9uIChpdGVtLCBsZXZlbCwgaXNOb2RlKSB7XG5cbiAgICAgICAgdmFyIHRvQkJveCA9IHRoaXMudG9CQm94LFxuICAgICAgICAgICAgYmJveCA9IGlzTm9kZSA/IGl0ZW0uYmJveCA6IHRvQkJveChpdGVtKSxcbiAgICAgICAgICAgIGluc2VydFBhdGggPSBbXTtcblxuICAgICAgICAvLyBmaW5kIHRoZSBiZXN0IG5vZGUgZm9yIGFjY29tbW9kYXRpbmcgdGhlIGl0ZW0sIHNhdmluZyBhbGwgbm9kZXMgYWxvbmcgdGhlIHBhdGggdG9vXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fY2hvb3NlU3VidHJlZShiYm94LCB0aGlzLmRhdGEsIGxldmVsLCBpbnNlcnRQYXRoKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGl0ZW0gaW50byB0aGUgbm9kZVxuICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goaXRlbSk7XG4gICAgICAgIGV4dGVuZChub2RlLmJib3gsIGJib3gpO1xuXG4gICAgICAgIC8vIHNwbGl0IG9uIG5vZGUgb3ZlcmZsb3c7IHByb3BhZ2F0ZSB1cHdhcmRzIGlmIG5lY2Vzc2FyeVxuICAgICAgICB3aGlsZSAobGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAgaWYgKGluc2VydFBhdGhbbGV2ZWxdLmNoaWxkcmVuLmxlbmd0aCA+IHRoaXMuX21heEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zcGxpdChpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgICAgICAgICAgICAgbGV2ZWwtLTtcbiAgICAgICAgICAgIH0gZWxzZSBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBiYm94ZXMgYWxvbmcgdGhlIGluc2VydGlvbiBwYXRoXG4gICAgICAgIHRoaXMuX2FkanVzdFBhcmVudEJCb3hlcyhiYm94LCBpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgfSxcblxuICAgIC8vIHNwbGl0IG92ZXJmbG93ZWQgbm9kZSBpbnRvIHR3b1xuICAgIF9zcGxpdDogZnVuY3Rpb24gKGluc2VydFBhdGgsIGxldmVsKSB7XG5cbiAgICAgICAgdmFyIG5vZGUgPSBpbnNlcnRQYXRoW2xldmVsXSxcbiAgICAgICAgICAgIE0gPSBub2RlLmNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICAgIG0gPSB0aGlzLl9taW5FbnRyaWVzO1xuXG4gICAgICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhub2RlLCBtLCBNKTtcblxuICAgICAgICB2YXIgbmV3Tm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLnNwbGljZSh0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pKSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobm9kZS5sZWFmKSBuZXdOb2RlLmxlYWYgPSB0cnVlO1xuXG4gICAgICAgIGNhbGNCQm94KG5vZGUsIHRoaXMudG9CQm94KTtcbiAgICAgICAgY2FsY0JCb3gobmV3Tm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIGlmIChsZXZlbCkgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIGVsc2UgdGhpcy5fc3BsaXRSb290KG5vZGUsIG5ld05vZGUpO1xuICAgIH0sXG5cbiAgICBfc3BsaXRSb290OiBmdW5jdGlvbiAobm9kZSwgbmV3Tm9kZSkge1xuICAgICAgICAvLyBzcGxpdCByb290IG5vZGVcbiAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtub2RlLCBuZXdOb2RlXSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHQgKyAxXG4gICAgICAgIH07XG4gICAgICAgIGNhbGNCQm94KHRoaXMuZGF0YSwgdGhpcy50b0JCb3gpO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3BsaXRJbmRleDogZnVuY3Rpb24gKG5vZGUsIG0sIE0pIHtcblxuICAgICAgICB2YXIgaSwgYmJveDEsIGJib3gyLCBvdmVybGFwLCBhcmVhLCBtaW5PdmVybGFwLCBtaW5BcmVhLCBpbmRleDtcblxuICAgICAgICBtaW5PdmVybGFwID0gbWluQXJlYSA9IEluZmluaXR5O1xuXG4gICAgICAgIGZvciAoaSA9IG07IGkgPD0gTSAtIG07IGkrKykge1xuICAgICAgICAgICAgYmJveDEgPSBkaXN0QkJveChub2RlLCAwLCBpLCB0aGlzLnRvQkJveCk7XG4gICAgICAgICAgICBiYm94MiA9IGRpc3RCQm94KG5vZGUsIGksIE0sIHRoaXMudG9CQm94KTtcblxuICAgICAgICAgICAgb3ZlcmxhcCA9IGludGVyc2VjdGlvbkFyZWEoYmJveDEsIGJib3gyKTtcbiAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShiYm94MSkgKyBiYm94QXJlYShiYm94Mik7XG5cbiAgICAgICAgICAgIC8vIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIG92ZXJsYXBcbiAgICAgICAgICAgIGlmIChvdmVybGFwIDwgbWluT3ZlcmxhcCkge1xuICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSBvdmVybGFwO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcblxuICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG92ZXJsYXAgPT09IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbmltdW0gYXJlYVxuICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICB9LFxuXG4gICAgLy8gc29ydHMgbm9kZSBjaGlsZHJlbiBieSB0aGUgYmVzdCBheGlzIGZvciBzcGxpdFxuICAgIF9jaG9vc2VTcGxpdEF4aXM6IGZ1bmN0aW9uIChub2RlLCBtLCBNKSB7XG5cbiAgICAgICAgdmFyIGNvbXBhcmVNaW5YID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWCA6IGNvbXBhcmVOb2RlTWluWCxcbiAgICAgICAgICAgIGNvbXBhcmVNaW5ZID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWSA6IGNvbXBhcmVOb2RlTWluWSxcbiAgICAgICAgICAgIHhNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5YKSxcbiAgICAgICAgICAgIHlNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5ZKTtcblxuICAgICAgICAvLyBpZiB0b3RhbCBkaXN0cmlidXRpb25zIG1hcmdpbiB2YWx1ZSBpcyBtaW5pbWFsIGZvciB4LCBzb3J0IGJ5IG1pblgsXG4gICAgICAgIC8vIG90aGVyd2lzZSBpdCdzIGFscmVhZHkgc29ydGVkIGJ5IG1pbllcbiAgICAgICAgaWYgKHhNYXJnaW4gPCB5TWFyZ2luKSBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZU1pblgpO1xuICAgIH0sXG5cbiAgICAvLyB0b3RhbCBtYXJnaW4gb2YgYWxsIHBvc3NpYmxlIHNwbGl0IGRpc3RyaWJ1dGlvbnMgd2hlcmUgZWFjaCBub2RlIGlzIGF0IGxlYXN0IG0gZnVsbFxuICAgIF9hbGxEaXN0TWFyZ2luOiBmdW5jdGlvbiAobm9kZSwgbSwgTSwgY29tcGFyZSkge1xuXG4gICAgICAgIG5vZGUuY2hpbGRyZW4uc29ydChjb21wYXJlKTtcblxuICAgICAgICB2YXIgdG9CQm94ID0gdGhpcy50b0JCb3gsXG4gICAgICAgICAgICBsZWZ0QkJveCA9IGRpc3RCQm94KG5vZGUsIDAsIG0sIHRvQkJveCksXG4gICAgICAgICAgICByaWdodEJCb3ggPSBkaXN0QkJveChub2RlLCBNIC0gbSwgTSwgdG9CQm94KSxcbiAgICAgICAgICAgIG1hcmdpbiA9IGJib3hNYXJnaW4obGVmdEJCb3gpICsgYmJveE1hcmdpbihyaWdodEJCb3gpLFxuICAgICAgICAgICAgaSwgY2hpbGQ7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGV4dGVuZChsZWZ0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4obGVmdEJCb3gpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gTSAtIG0gLSAxOyBpID49IG07IGktLSkge1xuICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgZXh0ZW5kKHJpZ2h0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4ocmlnaHRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXJnaW47XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgZXh0ZW5kKHBhdGhbaV0uYmJveCwgYmJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbmRlbnNlOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIHRoZSBwYXRoLCByZW1vdmluZyBlbXB0eSBub2RlcyBhbmQgdXBkYXRpbmcgYmJveGVzXG4gICAgICAgIGZvciAodmFyIGkgPSBwYXRoLmxlbmd0aCAtIDEsIHNpYmxpbmdzOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKHBhdGhbaV0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzID0gcGF0aFtpIC0gMV0uY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzLnNwbGljZShzaWJsaW5ncy5pbmRleE9mKHBhdGhbaV0pLCAxKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBjYWxjQkJveChwYXRoW2ldLCB0aGlzLnRvQkJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2luaXRGb3JtYXQ6IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgLy8gZGF0YSBmb3JtYXQgKG1pblgsIG1pblksIG1heFgsIG1heFkgYWNjZXNzb3JzKVxuXG4gICAgICAgIC8vIHVzZXMgZXZhbC10eXBlIGZ1bmN0aW9uIGNvbXBpbGF0aW9uIGluc3RlYWQgb2YganVzdCBhY2NlcHRpbmcgYSB0b0JCb3ggZnVuY3Rpb25cbiAgICAgICAgLy8gYmVjYXVzZSB0aGUgYWxnb3JpdGhtcyBhcmUgdmVyeSBzZW5zaXRpdmUgdG8gc29ydGluZyBmdW5jdGlvbnMgcGVyZm9ybWFuY2UsXG4gICAgICAgIC8vIHNvIHRoZXkgc2hvdWxkIGJlIGRlYWQgc2ltcGxlIGFuZCB3aXRob3V0IGlubmVyIGNhbGxzXG5cbiAgICAgICAgLy8ganNoaW50IGV2aWw6IHRydWVcblxuICAgICAgICB2YXIgY29tcGFyZUFyciA9IFsncmV0dXJuIGEnLCAnIC0gYicsICc7J107XG5cbiAgICAgICAgdGhpcy5jb21wYXJlTWluWCA9IG5ldyBGdW5jdGlvbignYScsICdiJywgY29tcGFyZUFyci5qb2luKGZvcm1hdFswXSkpO1xuICAgICAgICB0aGlzLmNvbXBhcmVNaW5ZID0gbmV3IEZ1bmN0aW9uKCdhJywgJ2InLCBjb21wYXJlQXJyLmpvaW4oZm9ybWF0WzFdKSk7XG5cbiAgICAgICAgdGhpcy50b0JCb3ggPSBuZXcgRnVuY3Rpb24oJ2EnLCAncmV0dXJuIFthJyArIGZvcm1hdC5qb2luKCcsIGEnKSArICddOycpO1xuICAgIH1cbn07XG5cblxuLy8gY2FsY3VsYXRlIG5vZGUncyBiYm94IGZyb20gYmJveGVzIG9mIGl0cyBjaGlsZHJlblxuZnVuY3Rpb24gY2FsY0JCb3gobm9kZSwgdG9CQm94KSB7XG4gICAgbm9kZS5iYm94ID0gZGlzdEJCb3gobm9kZSwgMCwgbm9kZS5jaGlsZHJlbi5sZW5ndGgsIHRvQkJveCk7XG59XG5cbi8vIG1pbiBib3VuZGluZyByZWN0YW5nbGUgb2Ygbm9kZSBjaGlsZHJlbiBmcm9tIGsgdG8gcC0xXG5mdW5jdGlvbiBkaXN0QkJveChub2RlLCBrLCBwLCB0b0JCb3gpIHtcbiAgICB2YXIgYmJveCA9IGVtcHR5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICBleHRlbmQoYmJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgIH1cblxuICAgIHJldHVybiBiYm94O1xufVxuXG5mdW5jdGlvbiBlbXB0eSgpIHsgcmV0dXJuIFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsgfVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGFbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBhWzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSk7XG4gICAgYVsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pO1xuICAgIGFbM10gPSBNYXRoLm1heChhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5YKGEsIGIpIHsgcmV0dXJuIGEuYmJveFswXSAtIGIuYmJveFswXTsgfVxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5ZKGEsIGIpIHsgcmV0dXJuIGEuYmJveFsxXSAtIGIuYmJveFsxXTsgfVxuXG5mdW5jdGlvbiBiYm94QXJlYShhKSAgIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKiAoYVszXSAtIGFbMV0pOyB9XG5mdW5jdGlvbiBiYm94TWFyZ2luKGEpIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKyAoYVszXSAtIGFbMV0pOyB9XG5cbmZ1bmN0aW9uIGVubGFyZ2VkQXJlYShhLCBiKSB7XG4gICAgcmV0dXJuIChNYXRoLm1heChiWzJdLCBhWzJdKSAtIE1hdGgubWluKGJbMF0sIGFbMF0pKSAqXG4gICAgICAgICAgIChNYXRoLm1heChiWzNdLCBhWzNdKSAtIE1hdGgubWluKGJbMV0sIGFbMV0pKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uQXJlYShhLCBiKSB7XG4gICAgdmFyIG1pblggPSBNYXRoLm1heChhWzBdLCBiWzBdKSxcbiAgICAgICAgbWluWSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pLFxuICAgICAgICBtYXhYID0gTWF0aC5taW4oYVsyXSwgYlsyXSksXG4gICAgICAgIG1heFkgPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcblxuICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICBNYXRoLm1heCgwLCBtYXhZIC0gbWluWSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSA8PSBiWzBdICYmXG4gICAgICAgICAgIGFbMV0gPD0gYlsxXSAmJlxuICAgICAgICAgICBiWzJdIDw9IGFbMl0gJiZcbiAgICAgICAgICAgYlszXSA8PSBhWzNdO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RzKGEsIGIpIHtcbiAgICByZXR1cm4gYlswXSA8PSBhWzJdICYmXG4gICAgICAgICAgIGJbMV0gPD0gYVszXSAmJlxuICAgICAgICAgICBiWzJdID49IGFbMF0gJiZcbiAgICAgICAgICAgYlszXSA+PSBhWzFdO1xufVxuXG4vLyBzb3J0IGFuIGFycmF5IHNvIHRoYXQgaXRlbXMgY29tZSBpbiBncm91cHMgb2YgbiB1bnNvcnRlZCBpdGVtcywgd2l0aCBncm91cHMgc29ydGVkIGJldHdlZW4gZWFjaCBvdGhlcjtcbi8vIGNvbWJpbmVzIHNlbGVjdGlvbiBhbGdvcml0aG0gd2l0aCBiaW5hcnkgZGl2aWRlICYgY29ucXVlciBhcHByb2FjaFxuXG5mdW5jdGlvbiBtdWx0aVNlbGVjdChhcnIsIGxlZnQsIHJpZ2h0LCBuLCBjb21wYXJlKSB7XG4gICAgdmFyIHN0YWNrID0gW2xlZnQsIHJpZ2h0XSxcbiAgICAgICAgbWlkO1xuXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgICAgICByaWdodCA9IHN0YWNrLnBvcCgpO1xuICAgICAgICBsZWZ0ID0gc3RhY2sucG9wKCk7XG5cbiAgICAgICAgaWYgKHJpZ2h0IC0gbGVmdCA8PSBuKSBjb250aW51ZTtcblxuICAgICAgICBtaWQgPSBsZWZ0ICsgTWF0aC5jZWlsKChyaWdodCAtIGxlZnQpIC8gbiAvIDIpICogbjtcbiAgICAgICAgc2VsZWN0KGFyciwgbGVmdCwgcmlnaHQsIG1pZCwgY29tcGFyZSk7XG5cbiAgICAgICAgc3RhY2sucHVzaChsZWZ0LCBtaWQsIG1pZCwgcmlnaHQpO1xuICAgIH1cbn1cblxuLy8gRmxveWQtUml2ZXN0IHNlbGVjdGlvbiBhbGdvcml0aG06XG4vLyBzb3J0IGFuIGFycmF5IGJldHdlZW4gbGVmdCBhbmQgcmlnaHQgKGluY2x1c2l2ZSkgc28gdGhhdCB0aGUgc21hbGxlc3QgayBlbGVtZW50cyBjb21lIGZpcnN0ICh1bm9yZGVyZWQpXG5mdW5jdGlvbiBzZWxlY3QoYXJyLCBsZWZ0LCByaWdodCwgaywgY29tcGFyZSkge1xuICAgIHZhciBuLCBpLCB6LCBzLCBzZCwgbmV3TGVmdCwgbmV3UmlnaHQsIHQsIGo7XG5cbiAgICB3aGlsZSAocmlnaHQgPiBsZWZ0KSB7XG4gICAgICAgIGlmIChyaWdodCAtIGxlZnQgPiA2MDApIHtcbiAgICAgICAgICAgIG4gPSByaWdodCAtIGxlZnQgKyAxO1xuICAgICAgICAgICAgaSA9IGsgLSBsZWZ0ICsgMTtcbiAgICAgICAgICAgIHogPSBNYXRoLmxvZyhuKTtcbiAgICAgICAgICAgIHMgPSAwLjUgKiBNYXRoLmV4cCgyICogeiAvIDMpO1xuICAgICAgICAgICAgc2QgPSAwLjUgKiBNYXRoLnNxcnQoeiAqIHMgKiAobiAtIHMpIC8gbikgKiAoaSAtIG4gLyAyIDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBuZXdMZWZ0ID0gTWF0aC5tYXgobGVmdCwgTWF0aC5mbG9vcihrIC0gaSAqIHMgLyBuICsgc2QpKTtcbiAgICAgICAgICAgIG5ld1JpZ2h0ID0gTWF0aC5taW4ocmlnaHQsIE1hdGguZmxvb3IoayArIChuIC0gaSkgKiBzIC8gbiArIHNkKSk7XG4gICAgICAgICAgICBzZWxlY3QoYXJyLCBuZXdMZWZ0LCBuZXdSaWdodCwgaywgY29tcGFyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0ID0gYXJyW2tdO1xuICAgICAgICBpID0gbGVmdDtcbiAgICAgICAgaiA9IHJpZ2h0O1xuXG4gICAgICAgIHN3YXAoYXJyLCBsZWZ0LCBrKTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYXJyW3JpZ2h0XSwgdCkgPiAwKSBzd2FwKGFyciwgbGVmdCwgcmlnaHQpO1xuXG4gICAgICAgIHdoaWxlIChpIDwgaikge1xuICAgICAgICAgICAgc3dhcChhcnIsIGksIGopO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgd2hpbGUgKGNvbXBhcmUoYXJyW2ldLCB0KSA8IDApIGkrKztcbiAgICAgICAgICAgIHdoaWxlIChjb21wYXJlKGFycltqXSwgdCkgPiAwKSBqLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29tcGFyZShhcnJbbGVmdF0sIHQpID09PSAwKSBzd2FwKGFyciwgbGVmdCwgaik7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgc3dhcChhcnIsIGosIHJpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqIDw9IGspIGxlZnQgPSBqICsgMTtcbiAgICAgICAgaWYgKGsgPD0gaikgcmlnaHQgPSBqIC0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoYXJyLCBpLCBqKSB7XG4gICAgdmFyIHRtcCA9IGFycltpXTtcbiAgICBhcnJbaV0gPSBhcnJbal07XG4gICAgYXJyW2pdID0gdG1wO1xufVxuXG5cbi8vIGV4cG9ydCBhcyBBTUQvQ29tbW9uSlMgbW9kdWxlIG9yIGdsb2JhbCB2YXJpYWJsZVxuaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgZGVmaW5lKCdyYnVzaCcsIGZ1bmN0aW9uKCkgeyByZXR1cm4gcmJ1c2g7IH0pO1xuZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpIG1vZHVsZS5leHBvcnRzID0gcmJ1c2g7XG5lbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHNlbGYucmJ1c2ggPSByYnVzaDtcbmVsc2Ugd2luZG93LnJidXNoID0gcmJ1c2g7XG5cbn0pKCk7XG4iLCIvLyBDb3B5cmlnaHQgMjAxNCBTaW1vbiBMeWRlbGxcclxuLy8gWDExICjigJxNSVTigJ0pIExpY2Vuc2VkLiAoU2VlIExJQ0VOU0UuKVxyXG5cclxudm9pZCAoZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkge1xyXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xyXG4gICAgZGVmaW5lKGZhY3RvcnkpXHJcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KClcclxuICB9IGVsc2Uge1xyXG4gICAgcm9vdC5yZXNvbHZlVXJsID0gZmFjdG9yeSgpXHJcbiAgfVxyXG59KHRoaXMsIGZ1bmN0aW9uKCkge1xyXG5cclxuICBmdW5jdGlvbiByZXNvbHZlVXJsKC8qIC4uLnVybHMgKi8pIHtcclxuICAgIHZhciBudW1VcmxzID0gYXJndW1lbnRzLmxlbmd0aFxyXG5cclxuICAgIGlmIChudW1VcmxzID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInJlc29sdmVVcmwgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50OyBnb3Qgbm9uZS5cIilcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYmFzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiYXNlXCIpXHJcbiAgICBiYXNlLmhyZWYgPSBhcmd1bWVudHNbMF1cclxuXHJcbiAgICBpZiAobnVtVXJscyA9PT0gMSkge1xyXG4gICAgICByZXR1cm4gYmFzZS5ocmVmXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImhlYWRcIilbMF1cclxuICAgIGhlYWQuaW5zZXJ0QmVmb3JlKGJhc2UsIGhlYWQuZmlyc3RDaGlsZClcclxuXHJcbiAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpXHJcbiAgICB2YXIgcmVzb2x2ZWRcclxuXHJcbiAgICBmb3IgKHZhciBpbmRleCA9IDE7IGluZGV4IDwgbnVtVXJsczsgaW5kZXgrKykge1xyXG4gICAgICBhLmhyZWYgPSBhcmd1bWVudHNbaW5kZXhdXHJcbiAgICAgIHJlc29sdmVkID0gYS5ocmVmXHJcbiAgICAgIGJhc2UuaHJlZiA9IHJlc29sdmVkXHJcbiAgICB9XHJcblxyXG4gICAgaGVhZC5yZW1vdmVDaGlsZChiYXNlKVxyXG5cclxuICAgIHJldHVybiByZXNvbHZlZFxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc29sdmVVcmxcclxuXHJcbn0pKTtcclxuIiwiLypcbiAqIENvcHlyaWdodCAoQykgMjAwOCBBcHBsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnNcbiAqIGFyZSBtZXQ6XG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodFxuICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGVcbiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIGBgQVMgSVMnJyBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuICogSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSXG4gKiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgQVBQTEUgSU5DLiBPUlxuICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sXG4gKiBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1JcbiAqIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gKiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICpcbiAqIFBvcnRlZCBmcm9tIFdlYmtpdFxuICogaHR0cDovL3N2bi53ZWJraXQub3JnL3JlcG9zaXRvcnkvd2Via2l0L3RydW5rL1NvdXJjZS9XZWJDb3JlL3BsYXRmb3JtL2dyYXBoaWNzL1VuaXRCZXppZXIuaFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gVW5pdEJlemllcjtcblxuZnVuY3Rpb24gVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpIHtcbiAgICAvLyBDYWxjdWxhdGUgdGhlIHBvbHlub21pYWwgY29lZmZpY2llbnRzLCBpbXBsaWNpdCBmaXJzdCBhbmQgbGFzdCBjb250cm9sIHBvaW50cyBhcmUgKDAsMCkgYW5kICgxLDEpLlxuICAgIHRoaXMuY3ggPSAzLjAgKiBwMXg7XG4gICAgdGhpcy5ieCA9IDMuMCAqIChwMnggLSBwMXgpIC0gdGhpcy5jeDtcbiAgICB0aGlzLmF4ID0gMS4wIC0gdGhpcy5jeCAtIHRoaXMuYng7XG5cbiAgICB0aGlzLmN5ID0gMy4wICogcDF5O1xuICAgIHRoaXMuYnkgPSAzLjAgKiAocDJ5IC0gcDF5KSAtIHRoaXMuY3k7XG4gICAgdGhpcy5heSA9IDEuMCAtIHRoaXMuY3kgLSB0aGlzLmJ5O1xuXG4gICAgdGhpcy5wMXggPSBwMXg7XG4gICAgdGhpcy5wMXkgPSBwMnk7XG4gICAgdGhpcy5wMnggPSBwMng7XG4gICAgdGhpcy5wMnkgPSBwMnk7XG59XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWCA9IGZ1bmN0aW9uKHQpIHtcbiAgICAvLyBgYXggdF4zICsgYnggdF4yICsgY3ggdCcgZXhwYW5kZWQgdXNpbmcgSG9ybmVyJ3MgcnVsZS5cbiAgICByZXR1cm4gKCh0aGlzLmF4ICogdCArIHRoaXMuYngpICogdCArIHRoaXMuY3gpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWSA9IGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gKCh0aGlzLmF5ICogdCArIHRoaXMuYnkpICogdCArIHRoaXMuY3kpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVggPSBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuICgzLjAgKiB0aGlzLmF4ICogdCArIDIuMCAqIHRoaXMuYngpICogdCArIHRoaXMuY3g7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zb2x2ZUN1cnZlWCA9IGZ1bmN0aW9uKHgsIGVwc2lsb24pIHtcbiAgICBpZiAodHlwZW9mIGVwc2lsb24gPT09ICd1bmRlZmluZWQnKSBlcHNpbG9uID0gMWUtNjtcblxuICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgaTtcblxuICAgIC8vIEZpcnN0IHRyeSBhIGZldyBpdGVyYXRpb25zIG9mIE5ld3RvbidzIG1ldGhvZCAtLSBub3JtYWxseSB2ZXJ5IGZhc3QuXG4gICAgZm9yICh0MiA9IHgsIGkgPSAwOyBpIDwgODsgaSsrKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0MikgLSB4O1xuICAgICAgICBpZiAoTWF0aC5hYnMoeDIpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIHZhciBkMiA9IHRoaXMuc2FtcGxlQ3VydmVEZXJpdmF0aXZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyhkMikgPCAxZS02KSBicmVhaztcblxuICAgICAgICB0MiA9IHQyIC0geDIgLyBkMjtcbiAgICB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gdGhlIGJpc2VjdGlvbiBtZXRob2QgZm9yIHJlbGlhYmlsaXR5LlxuICAgIHQwID0gMC4wO1xuICAgIHQxID0gMS4wO1xuICAgIHQyID0geDtcblxuICAgIGlmICh0MiA8IHQwKSByZXR1cm4gdDA7XG4gICAgaWYgKHQyID4gdDEpIHJldHVybiB0MTtcblxuICAgIHdoaWxlICh0MCA8IHQxKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyh4MiAtIHgpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIGlmICh4ID4geDIpIHtcbiAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0MSA9IHQyO1xuICAgICAgICB9XG5cbiAgICAgICAgdDIgPSAodDEgLSB0MCkgKiAwLjUgKyB0MDtcbiAgICB9XG5cbiAgICAvLyBGYWlsdXJlLlxuICAgIHJldHVybiB0Mjtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNvbHZlID0gZnVuY3Rpb24oeCwgZXBzaWxvbikge1xuICAgIHJldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHgsIGVwc2lsb24pKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cy5WZWN0b3JUaWxlID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCcuL2xpYi92ZWN0b3J0aWxlZmVhdHVyZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUxheWVyID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZWxheWVyLmpzJyk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlTGF5ZXIgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGVsYXllcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZlY3RvclRpbGU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGUocGJmLCBlbmQpIHtcbiAgICB0aGlzLmxheWVycyA9IHBiZi5yZWFkRmllbGRzKHJlYWRUaWxlLCB7fSwgZW5kKTtcbn1cblxuZnVuY3Rpb24gcmVhZFRpbGUodGFnLCBsYXllcnMsIHBiZikge1xuICAgIGlmICh0YWcgPT09IDMpIHtcbiAgICAgICAgdmFyIGxheWVyID0gbmV3IFZlY3RvclRpbGVMYXllcihwYmYsIHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zKTtcbiAgICAgICAgaWYgKGxheWVyLmxlbmd0aCkgbGF5ZXJzW2xheWVyLm5hbWVdID0gbGF5ZXI7XG4gICAgfVxufVxuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmVjdG9yVGlsZUZlYXR1cmU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVGZWF0dXJlKHBiZiwgZW5kLCBleHRlbnQsIGtleXMsIHZhbHVlcykge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMucHJvcGVydGllcyA9IHt9O1xuICAgIHRoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIHRoaXMudHlwZSA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fcGJmID0gcGJmO1xuICAgIHRoaXMuX2dlb21ldHJ5ID0gLTE7XG4gICAgdGhpcy5fa2V5cyA9IGtleXM7XG4gICAgdGhpcy5fdmFsdWVzID0gdmFsdWVzO1xuXG4gICAgcGJmLnJlYWRGaWVsZHMocmVhZEZlYXR1cmUsIHRoaXMsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRGZWF0dXJlKHRhZywgZmVhdHVyZSwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PSAxKSBmZWF0dXJlLl9pZCA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgZWxzZSBpZiAodGFnID09IDIpIHJlYWRUYWcocGJmLCBmZWF0dXJlKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gMykgZmVhdHVyZS50eXBlID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gNCkgZmVhdHVyZS5fZ2VvbWV0cnkgPSBwYmYucG9zO1xufVxuXG5mdW5jdGlvbiByZWFkVGFnKHBiZiwgZmVhdHVyZSkge1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhciBrZXkgPSBmZWF0dXJlLl9rZXlzW3BiZi5yZWFkVmFyaW50KCldLFxuICAgICAgICAgICAgdmFsdWUgPSBmZWF0dXJlLl92YWx1ZXNbcGJmLnJlYWRWYXJpbnQoKV07XG4gICAgICAgIGZlYXR1cmUucHJvcGVydGllc1trZXldID0gdmFsdWU7XG4gICAgfVxufVxuXG5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyA9IFsnVW5rbm93bicsICdQb2ludCcsICdMaW5lU3RyaW5nJywgJ1BvbHlnb24nXTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIGxpbmVzID0gW10sXG4gICAgICAgIGxpbmU7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGNtZExlbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgICAgICAgICBjbWQgPSBjbWRMZW4gJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRMZW4gPj4gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGxlbmd0aC0tO1xuXG4gICAgICAgIGlmIChjbWQgPT09IDEgfHwgY21kID09PSAyKSB7XG4gICAgICAgICAgICB4ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgeSArPSBwYmYucmVhZFNWYXJpbnQoKTtcblxuICAgICAgICAgICAgaWYgKGNtZCA9PT0gMSkgeyAvLyBtb3ZlVG9cbiAgICAgICAgICAgICAgICBpZiAobGluZSkgbGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUucHVzaChuZXcgUG9pbnQoeCwgeSkpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kID09PSA3KSB7XG4gICAgICAgICAgICBsaW5lLnB1c2gobGluZVswXS5jbG9uZSgpKTsgLy8gY2xvc2VQb2x5Z29uXG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxpbmUpIGxpbmVzLnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gbGluZXM7XG59O1xuXG5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgY21kTGVuID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZExlbiAmIDB4NztcbiAgICAgICAgICAgIGxlbmd0aCA9IGNtZExlbiA+PiAzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVuZ3RoLS07XG5cbiAgICAgICAgaWYgKGNtZCA9PT0gMSB8fCBjbWQgPT09IDIpIHtcbiAgICAgICAgICAgIHggKz0gcGJmLnJlYWRTVmFyaW50KCk7XG4gICAgICAgICAgICB5ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgaWYgKHggPCB4MSkgeDEgPSB4O1xuICAgICAgICAgICAgaWYgKHggPiB4MikgeDIgPSB4O1xuICAgICAgICAgICAgaWYgKHkgPCB5MSkgeTEgPSB5O1xuICAgICAgICAgICAgaWYgKHkgPiB5MikgeTIgPSB5O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kICE9PSA3KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vua25vd24gY29tbWFuZCAnICsgY21kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbeDEsIHkxLCB4MiwgeTJdO1xufTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZXh0ZW50ICogTWF0aC5wb3coMiwgeiksXG4gICAgICAgIHgwID0gdGhpcy5leHRlbnQgKiB4LFxuICAgICAgICB5MCA9IHRoaXMuZXh0ZW50ICogeSxcbiAgICAgICAgY29vcmRzID0gdGhpcy5sb2FkR2VvbWV0cnkoKSxcbiAgICAgICAgdHlwZSA9IFZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW3RoaXMudHlwZV07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGNvb3Jkc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsaW5lLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGxpbmVbal0sIHkyID0gMTgwIC0gKHAueSArIHkwKSAqIDM2MCAvIHNpemU7XG4gICAgICAgICAgICBsaW5lW2pdID0gW1xuICAgICAgICAgICAgICAgIChwLnggKyB4MCkgKiAzNjAgLyBzaXplIC0gMTgwLFxuICAgICAgICAgICAgICAgIDM2MCAvIE1hdGguUEkgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIgKiBNYXRoLlBJIC8gMTgwKSkgLSA5MFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnUG9pbnQnICYmIGNvb3Jkcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY29vcmRzID0gY29vcmRzWzBdWzBdO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgICAgIHR5cGUgPSAnTXVsdGlQb2ludCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycgJiYgY29vcmRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycpIHtcbiAgICAgICAgdHlwZSA9ICdNdWx0aUxpbmVTdHJpbmcnO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHNcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZSA9IHJlcXVpcmUoJy4vdmVjdG9ydGlsZWZlYXR1cmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVMYXllcihwYmYsIGVuZCkge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMudmVyc2lvbiA9IDE7XG4gICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICB0aGlzLmV4dGVudCA9IDQwOTY7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuXG4gICAgLy8gUHJpdmF0ZVxuICAgIHRoaXMuX3BiZiA9IHBiZjtcbiAgICB0aGlzLl9rZXlzID0gW107XG4gICAgdGhpcy5fdmFsdWVzID0gW107XG4gICAgdGhpcy5fZmVhdHVyZXMgPSBbXTtcblxuICAgIHBiZi5yZWFkRmllbGRzKHJlYWRMYXllciwgdGhpcywgZW5kKTtcblxuICAgIHRoaXMubGVuZ3RoID0gdGhpcy5fZmVhdHVyZXMubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiByZWFkTGF5ZXIodGFnLCBsYXllciwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMTUpIGxheWVyLnZlcnNpb24gPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMSkgbGF5ZXIubmFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSA1KSBsYXllci5leHRlbnQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgbGF5ZXIuX2ZlYXR1cmVzLnB1c2gocGJmLnBvcyk7XG4gICAgZWxzZSBpZiAodGFnID09PSAzKSBsYXllci5fa2V5cy5wdXNoKHBiZi5yZWFkU3RyaW5nKCkpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgbGF5ZXIuX3ZhbHVlcy5wdXNoKHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSB7XG4gICAgdmFyIHZhbHVlID0gbnVsbCxcbiAgICAgICAgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICB2YXIgdGFnID0gcGJmLnJlYWRWYXJpbnQoKSA+PiAzO1xuXG4gICAgICAgIHZhbHVlID0gdGFnID09PSAxID8gcGJmLnJlYWRTdHJpbmcoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDIgPyBwYmYucmVhZEZsb2F0KCkgOlxuICAgICAgICAgICAgdGFnID09PSAzID8gcGJmLnJlYWREb3VibGUoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDQgPyBwYmYucmVhZFZhcmludDY0KCkgOlxuICAgICAgICAgICAgdGFnID09PSA1ID8gcGJmLnJlYWRWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDYgPyBwYmYucmVhZFNWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDcgPyBwYmYucmVhZEJvb2xlYW4oKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufVxuXG4vLyByZXR1cm4gZmVhdHVyZSBgaWAgZnJvbSB0aGlzIGxheWVyIGFzIGEgYFZlY3RvclRpbGVGZWF0dXJlYFxuVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5mZWF0dXJlID0gZnVuY3Rpb24oaSkge1xuICAgIGlmIChpIDwgMCB8fCBpID49IHRoaXMuX2ZlYXR1cmVzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHMnKTtcblxuICAgIHRoaXMuX3BiZi5wb3MgPSB0aGlzLl9mZWF0dXJlc1tpXTtcblxuICAgIHZhciBlbmQgPSB0aGlzLl9wYmYucmVhZFZhcmludCgpICsgdGhpcy5fcGJmLnBvcztcbiAgICByZXR1cm4gbmV3IFZlY3RvclRpbGVGZWF0dXJlKHRoaXMuX3BiZiwgZW5kLCB0aGlzLmV4dGVudCwgdGhpcy5fa2V5cywgdGhpcy5fdmFsdWVzKTtcbn07XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsInZhciBidW5kbGVGbiA9IGFyZ3VtZW50c1szXTtcbnZhciBzb3VyY2VzID0gYXJndW1lbnRzWzRdO1xudmFyIGNhY2hlID0gYXJndW1lbnRzWzVdO1xuXG52YXIgc3RyaW5naWZ5ID0gSlNPTi5zdHJpbmdpZnk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICB2YXIgd2tleTtcbiAgICB2YXIgY2FjaGVLZXlzID0gT2JqZWN0LmtleXMoY2FjaGUpO1xuICAgIFxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2FjaGVLZXlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICBpZiAoY2FjaGVba2V5XS5leHBvcnRzID09PSBmbikge1xuICAgICAgICAgICAgd2tleSA9IGtleTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlmICghd2tleSkge1xuICAgICAgICB3a2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgICAgIHZhciB3Y2FjaGUgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjYWNoZUtleXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICAgICAgd2NhY2hlW2tleV0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgICAgc291cmNlc1t3a2V5XSA9IFtcbiAgICAgICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZScsJ21vZHVsZScsJ2V4cG9ydHMnXSwgJygnICsgZm4gKyAnKShzZWxmKScpLFxuICAgICAgICAgICAgd2NhY2hlXG4gICAgICAgIF07XG4gICAgfVxuICAgIHZhciBza2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgXG4gICAgdmFyIHNjYWNoZSA9IHt9OyBzY2FjaGVbd2tleV0gPSB3a2V5O1xuICAgIHNvdXJjZXNbc2tleV0gPSBbXG4gICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZSddLCdyZXF1aXJlKCcgKyBzdHJpbmdpZnkod2tleSkgKyAnKShzZWxmKScpLFxuICAgICAgICBzY2FjaGVcbiAgICBdO1xuICAgIFxuICAgIHZhciBzcmMgPSAnKCcgKyBidW5kbGVGbiArICcpKHsnXG4gICAgICAgICsgT2JqZWN0LmtleXMoc291cmNlcykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdpZnkoa2V5KSArICc6WydcbiAgICAgICAgICAgICAgICArIHNvdXJjZXNba2V5XVswXVxuICAgICAgICAgICAgICAgICsgJywnICsgc3RyaW5naWZ5KHNvdXJjZXNba2V5XVsxXSkgKyAnXSdcbiAgICAgICAgICAgIDtcbiAgICAgICAgfSkuam9pbignLCcpXG4gICAgICAgICsgJ30se30sWycgKyBzdHJpbmdpZnkoc2tleSkgKyAnXSknXG4gICAgO1xuICAgIFxuICAgIHZhciBVUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkwgfHwgd2luZG93Lm1velVSTCB8fCB3aW5kb3cubXNVUkw7XG4gICAgXG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoVVJMLmNyZWF0ZU9iamVjdFVSTChcbiAgICAgICAgbmV3IEJsb2IoW3NyY10sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSlcbiAgICApKTtcbn07XG4iXX0= >>>>>>> Stashed changes